You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
| 2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
| 2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
| 2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
| 2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
| 2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
| 2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
| 2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
| 2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
| 2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
| 2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <fwi...@us...> - 2011-03-25 15:25:14
|
Revision: 7267
http://jython.svn.sourceforge.net/jython/?rev=7267&view=rev
Author: fwierzbicki
Date: 2011-03-25 15:25:07 +0000 (Fri, 25 Mar 2011)
Log Message:
-----------
Reformat so that I can more easily script the removal of the grammar actions. I
am probably going to need another parser to check "from __future__".
Modified Paths:
--------------
trunk/jython/grammar/Python.g
Modified: trunk/jython/grammar/Python.g
===================================================================
--- trunk/jython/grammar/Python.g 2011-03-24 20:12:46 UTC (rev 7266)
+++ trunk/jython/grammar/Python.g 2011-03-25 15:25:07 UTC (rev 7267)
@@ -267,6 +267,8 @@
}
}
+//START OF PARSER RULES
+
//single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
single_input
@init {
@@ -318,8 +320,9 @@
: (NEWLINE
| stmt
{
- if ($stmt.stypes != null)
- {stypes.addAll($stmt.stypes);}
+ if ($stmt.stypes != null) {
+ stypes.addAll($stmt.stypes);
+ }
}
)* EOF
{
@@ -446,8 +449,13 @@
//funcdef: [decorators] 'def' NAME parameters ':' suite
funcdef
-@init { stmt stype = null; }
-@after { $funcdef.tree = stype; }
+@init {
+ stmt stype = null;
+}
+
+@after {
+ $funcdef.tree = stype;
+}
: decorators? DEF NAME parameters COLON suite[false]
{
Token t = $DEF;
@@ -625,29 +633,53 @@
augassign
returns [operatorType op]
: PLUSEQUAL
- {$op = operatorType.Add;}
+ {
+ $op = operatorType.Add;
+ }
| MINUSEQUAL
- {$op = operatorType.Sub;}
+ {
+ $op = operatorType.Sub;
+ }
| STAREQUAL
- {$op = operatorType.Mult;}
+ {
+ $op = operatorType.Mult;
+ }
| SLASHEQUAL
- {$op = operatorType.Div;}
+ {
+ $op = operatorType.Div;
+ }
| PERCENTEQUAL
- {$op = operatorType.Mod;}
+ {
+ $op = operatorType.Mod;
+ }
| AMPEREQUAL
- {$op = operatorType.BitAnd;}
+ {
+ $op = operatorType.BitAnd;
+ }
| VBAREQUAL
- {$op = operatorType.BitOr;}
+ {
+ $op = operatorType.BitOr;
+ }
| CIRCUMFLEXEQUAL
- {$op = operatorType.BitXor;}
+ {
+ $op = operatorType.BitXor;
+ }
| LEFTSHIFTEQUAL
- {$op = operatorType.LShift;}
+ {
+ $op = operatorType.LShift;
+ }
| RIGHTSHIFTEQUAL
- {$op = operatorType.RShift;}
+ {
+ $op = operatorType.RShift;
+ }
| DOUBLESTAREQUAL
- {$op = operatorType.Pow;}
+ {
+ $op = operatorType.Pow;
+ }
| DOUBLESLASHEQUAL
- {$op = operatorType.FloorDiv;}
+ {
+ $op = operatorType.FloorDiv;
+ }
;
//print_stmt: 'print' ( [ test (',' test)* [','] ] |
@@ -1085,7 +1117,10 @@
[expr_contextType ctype] returns [Token leftTok]
: NOT nt=not_test[ctype]
-> ^(NOT<UnaryOp>[$NOT, unaryopType.Not, actions.castExpr($nt.tree)])
- | comparison[ctype] {$leftTok = $comparison.leftTok;}
+ | comparison[ctype]
+ {
+ $leftTok = $comparison.leftTok;
+ }
;
//comparison: expr (comp_op expr)*
@@ -1116,27 +1151,49 @@
comp_op
returns [cmpopType op]
: LESS
- {$op = cmpopType.Lt;}
+ {
+ $op = cmpopType.Lt;
+ }
| GREATER
- {$op = cmpopType.Gt;}
+ {
+ $op = cmpopType.Gt;
+ }
| EQUAL
- {$op = cmpopType.Eq;}
+ {
+ $op = cmpopType.Eq;
+ }
| GREATEREQUAL
- {$op = cmpopType.GtE;}
+ {
+ $op = cmpopType.GtE;
+ }
| LESSEQUAL
- {$op = cmpopType.LtE;}
+ {
+ $op = cmpopType.LtE;
+ }
| ALT_NOTEQUAL
- {$op = cmpopType.NotEq;}
+ {
+ $op = cmpopType.NotEq;
+ }
| NOTEQUAL
- {$op = cmpopType.NotEq;}
+ {
+ $op = cmpopType.NotEq;
+ }
| IN
- {$op = cmpopType.In;}
+ {
+ $op = cmpopType.In;
+ }
| NOT IN
- {$op = cmpopType.NotIn;}
+ {
+ $op = cmpopType.NotIn;
+ }
| IS
- {$op = cmpopType.Is;}
+ {
+ $op = cmpopType.Is;
+ }
| IS NOT
- {$op = cmpopType.IsNot;}
+ {
+ $op = cmpopType.IsNot;
+ }
;
@@ -1242,9 +1299,13 @@
shift_op
returns [operatorType op]
: LEFTSHIFT
- {$op = operatorType.LShift;}
+ {
+ $op = operatorType.LShift;
+ }
| RIGHTSHIFT
- {$op = operatorType.RShift;}
+ {
+ $op = operatorType.RShift;
+ }
;
//arith_expr: term (('+'|'-') term)*
@@ -1287,9 +1348,13 @@
arith_op
returns [operatorType op]
: PLUS
- {$op = operatorType.Add;}
+ {
+ $op = operatorType.Add;
+ }
| MINUS
- {$op = operatorType.Sub;}
+ {
+ $op = operatorType.Sub;
+ }
;
//term: factor (('*'|'/'|'%'|'//') factor)*
@@ -1323,14 +1388,22 @@
term_op
returns [operatorType op]
- :STAR
- {$op = operatorType.Mult;}
- |SLASH
- {$op = operatorType.Div;}
- |PERCENT
- {$op = operatorType.Mod;}
- |DOUBLESLASH
- {$op = operatorType.FloorDiv;}
+ : STAR
+ {
+ $op = operatorType.Mult;
+ }
+ | SLASH
+ {
+ $op = operatorType.Div;
+ }
+ | PERCENT
+ {
+ $op = operatorType.Mod;
+ }
+ | DOUBLESLASH
+ {
+ $op = operatorType.FloorDiv;
+ }
;
//factor: ('+'|'-'|'~') factor | power
@@ -1340,11 +1413,17 @@
$factor.tree = $etype;
}
: PLUS p=factor
- {$etype = new UnaryOp($PLUS, unaryopType.UAdd, $p.etype);}
+ {
+ $etype = new UnaryOp($PLUS, unaryopType.UAdd, $p.etype);
+ }
| MINUS m=factor
- {$etype = actions.negate($MINUS, $m.etype);}
+ {
+ $etype = actions.negate($MINUS, $m.etype);
+ }
| TILDE t=factor
- {$etype = new UnaryOp($TILDE, unaryopType.Invert, $t.etype);}
+ {
+ $etype = new UnaryOp($TILDE, unaryopType.Invert, $t.etype);
+ }
| power
{
$etype = actions.castExpr($power.tree);
@@ -1399,7 +1478,10 @@
// NAME | NUMBER | STRING+)
atom
returns [Token lparen = null]
- : LPAREN {$lparen = $LPAREN;}
+ : LPAREN
+ {
+ $lparen = $LPAREN;
+ }
( yield_expr
-> yield_expr
| testlist_gexp
@@ -1475,8 +1557,7 @@
}
: t+=test[$expr::ctype]
( ((options {k=2;}: c1=COMMA t+=test[$expr::ctype])* (c2=COMMA)?
- -> { $c1 != null || $c2 != null }?
- ^(COMMA<Tuple>[$testlist_gexp.start, actions.castExprs($t), $expr::ctype])
+ -> { $c1 != null || $c2 != null }? ^(COMMA<Tuple>[$testlist_gexp.start, actions.castExprs($t), $expr::ctype])
-> test
)
| (gen_for[gens]
@@ -1778,6 +1859,7 @@
-> ^(YIELD<Yield>[$YIELD, actions.castExpr($testlist.tree)])
;
+//START OF LEXER RULES
AS : 'as' ;
ASSERT : 'assert' ;
BREAK : 'break' ;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-24 20:12:52
|
Revision: 7266
http://jython.svn.sourceforge.net/jython/?rev=7266&view=rev
Author: pjenvey
Date: 2011-03-24 20:12:46 +0000 (Thu, 24 Mar 2011)
Log Message:
-----------
fix zipimporter subclasses not getting a __dict__
test from Yuji Yamano (thanks)
Modified Paths:
--------------
trunk/jython/Lib/test/test_zipimport_jy.py
trunk/jython/src/org/python/modules/zipimport/zipimporterDerived.java
trunk/jython/src/templates/zipimporter.derived
Modified: trunk/jython/Lib/test/test_zipimport_jy.py
===================================================================
--- trunk/jython/Lib/test/test_zipimport_jy.py 2011-03-24 20:11:52 UTC (rev 7265)
+++ trunk/jython/Lib/test/test_zipimport_jy.py 2011-03-24 20:12:46 UTC (rev 7266)
@@ -1,8 +1,8 @@
import unittest
import sys
import java.lang.Package
-
from test import test_support
+from zipimport import zipimporter
class SyspathZipimportTest(unittest.TestCase):
def setUp(self):
@@ -10,7 +10,7 @@
sys.path.insert(0, test_support.findfile("syspath_import.jar"))
# TODO confirm that package is unloaded via a phantom ref or something like that
-
+
def tearDown(self):
sys.path = self.orig_path
@@ -31,6 +31,17 @@
from syspathpkg import module
self.assertEquals(module.__name__, 'syspathpkg.module')
+ def test_zipimporter_subclass(self):
+ class MyJavaClass(zipimporter):
+ def __init__(self):
+ zipimporter.__init__(self, test_support.findfile('zipdir.zip'))
+ self.bar = "bar"
+
+ # Previously failed with AttributeError: 'MyJavaClass' object
+ # has no attribute 'bar'
+ obj = MyJavaClass()
+ self.assertTrue(isinstance(obj, zipimporter))
+
def test_main():
test_support.run_unittest(SyspathZipimportTest)
Modified: trunk/jython/src/org/python/modules/zipimport/zipimporterDerived.java
===================================================================
--- trunk/jython/src/org/python/modules/zipimport/zipimporterDerived.java 2011-03-24 20:11:52 UTC (rev 7265)
+++ trunk/jython/src/org/python/modules/zipimport/zipimporterDerived.java 2011-03-24 20:12:46 UTC (rev 7266)
@@ -16,9 +16,33 @@
private PyObject[]slots;
+ private PyObject dict;
+
+ public PyObject fastGetDict() {
+ return dict;
+ }
+
+ public PyObject getDict() {
+ return dict;
+ }
+
+ public void setDict(PyObject newDict) {
+ if (newDict instanceof PyStringMap||newDict instanceof PyDictionary) {
+ dict=newDict;
+ } else {
+ throw Py.TypeError("__dict__ must be set to a Dictionary "+newDict.getClass().getName());
+ }
+ }
+
+ public void delDict() {
+ // deleting an object's instance dict makes it grow a new one
+ dict=new PyStringMap();
+ }
+
public zipimporterDerived(PyType subtype) {
super(subtype);
slots=new PyObject[subtype.getNumSlots()];
+ dict=subtype.instDict();
}
public PyString __str__() {
Modified: trunk/jython/src/templates/zipimporter.derived
===================================================================
--- trunk/jython/src/templates/zipimporter.derived 2011-03-24 20:11:52 UTC (rev 7265)
+++ trunk/jython/src/templates/zipimporter.derived 2011-03-24 20:12:46 UTC (rev 7266)
@@ -1,4 +1,4 @@
base_class: zipimporter
-want_dict: false
+want_dict: true
ctr:
incl: object
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-24 20:11:58
|
Revision: 7265
http://jython.svn.sourceforge.net/jython/?rev=7265&view=rev
Author: pjenvey
Date: 2011-03-24 20:11:52 +0000 (Thu, 24 Mar 2011)
Log Message:
-----------
oops, always null out message here
Modified Paths:
--------------
trunk/jython/src/org/python/core/PyBaseException.java
Modified: trunk/jython/src/org/python/core/PyBaseException.java
===================================================================
--- trunk/jython/src/org/python/core/PyBaseException.java 2011-03-24 02:08:13 UTC (rev 7264)
+++ trunk/jython/src/org/python/core/PyBaseException.java 2011-03-24 20:11:52 UTC (rev 7265)
@@ -254,7 +254,7 @@
public void delMessage() {
if (__dict__ != null && (message = __dict__.__finditem__("message")) != null) {
__dict__.__delitem__("message");
- message = null;
}
+ message = null;
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fwi...@us...> - 2011-03-24 02:08:19
|
Revision: 7264
http://jython.svn.sourceforge.net/jython/?rev=7264&view=rev
Author: fwierzbicki
Date: 2011-03-24 02:08:13 +0000 (Thu, 24 Mar 2011)
Log Message:
-----------
Move code back to it's relevant comment.
Modified Paths:
--------------
trunk/jython/grammar/Python.g
Modified: trunk/jython/grammar/Python.g
===================================================================
--- trunk/jython/grammar/Python.g 2011-03-24 01:01:57 UTC (rev 7263)
+++ trunk/jython/grammar/Python.g 2011-03-24 02:08:13 UTC (rev 7264)
@@ -205,15 +205,14 @@
* a = [3,
* 4]
*/
+int implicitLineJoiningLevel = 0;
+int startPos=-1;
//For use in partial parsing.
public boolean eofWhileNested = false;
public boolean partial = false;
public boolean single = false;
-int implicitLineJoiningLevel = 0;
-int startPos=-1;
-
//If you want to use another error recovery mechanism change this
//and the same one in the parser.
private ErrorHandler errorHandler;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fwi...@us...> - 2011-03-24 01:02:03
|
Revision: 7263
http://jython.svn.sourceforge.net/jython/?rev=7263&view=rev
Author: fwierzbicki
Date: 2011-03-24 01:01:57 +0000 (Thu, 24 Mar 2011)
Log Message:
-----------
Glob in Java to speed up grammar regression tests.
Modified Paths:
--------------
trunk/sandbox/wierzbicki/antlr/run
trunk/sandbox/wierzbicki/antlr/src/Main.java
Modified: trunk/sandbox/wierzbicki/antlr/run
===================================================================
--- trunk/sandbox/wierzbicki/antlr/run 2011-03-23 05:03:29 UTC (rev 7262)
+++ trunk/sandbox/wierzbicki/antlr/run 2011-03-24 01:01:57 UTC (rev 7263)
@@ -1 +1 @@
-java -classpath lib/antlr-3.1.jar:build Main $*
+java -classpath lib/antlr-3.1.jar:build Main /home/frank/svn/python/release26-maint
Modified: trunk/sandbox/wierzbicki/antlr/src/Main.java
===================================================================
--- trunk/sandbox/wierzbicki/antlr/src/Main.java 2011-03-23 05:03:29 UTC (rev 7262)
+++ trunk/sandbox/wierzbicki/antlr/src/Main.java 2011-03-24 01:01:57 UTC (rev 7263)
@@ -6,24 +6,46 @@
public class Main {
// override nextToken to set startPos (this seems too hard)
public static class MyLexer extends PythonLexer {
- public MyLexer(CharStream lexer) {
- super(lexer);
- }
- public Token nextToken() {
- startPos = getCharPositionInLine();
- return super.nextToken();
- }
+ public MyLexer(CharStream lexer) {
+ super(lexer);
+ }
+ public Token nextToken() {
+ startPos = getCharPositionInLine();
+ return super.nextToken();
+ }
}
public static void main(String[] args) throws Exception {
- CharStream input = new ANTLRFileStream(args[0]);
- PythonLexer lexer = new MyLexer(input);
- CommonTokenStream tokens = new CommonTokenStream(lexer);
- tokens.discardOffChannelTokens(true);
- PythonTokenSource indentedSource = new PythonTokenSource(tokens, "<test>");
- tokens = new CommonTokenStream(indentedSource);
- //System.out.println("tokens="+tokens.getTokens());
- PythonParser parser = new PythonParser(tokens);
- parser.file_input();
+ walk(new File(args[0]));
}
+
+ public static void walk(File dir) throws Exception {
+ String pattern = ".py";
+
+ File pyfiles[] = dir.listFiles();
+ if(pyfiles != null) {
+ for(int i=0; i<pyfiles.length; i++) {
+ if(pyfiles[i].isDirectory()) {
+ walk(pyfiles[i]);
+ } else {
+ if(pyfiles[i].getName().endsWith(pattern)) {
+ run(pyfiles[i].getPath());
+ }
+ }
+ }
+ }
+ }
+
+
+ public static void run(String path) throws Exception {
+ System.out.println("parsing " + path);
+ CharStream input = new ANTLRFileStream(path);
+ PythonLexer lexer = new MyLexer(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+ tokens.discardOffChannelTokens(true);
+ PythonTokenSource indentedSource = new PythonTokenSource(tokens, "<test>");
+ tokens = new CommonTokenStream(indentedSource);
+ PythonParser parser = new PythonParser(tokens);
+ parser.file_input();
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fwi...@us...> - 2011-03-23 05:03:36
|
Revision: 7262
http://jython.svn.sourceforge.net/jython/?rev=7262&view=rev
Author: fwierzbicki
Date: 2011-03-23 05:03:29 +0000 (Wed, 23 Mar 2011)
Log Message:
-----------
Update to 2.6 platform.py.
Modified Paths:
--------------
trunk/jython/Lib/platform.py
Modified: trunk/jython/Lib/platform.py
===================================================================
--- trunk/jython/Lib/platform.py 2011-03-22 02:38:16 UTC (rev 7261)
+++ trunk/jython/Lib/platform.py 2011-03-23 05:03:29 UTC (rev 7262)
@@ -10,7 +10,7 @@
"""
# This module is maintained by Marc-Andre Lemburg <ma...@eg...>.
# If you find problems, please submit bug reports/patches via the
-# Python SourceForge Project Page and assign them to "lemburg".
+# Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
#
# Note: Please keep this module compatible to Python 1.5.2.
#
@@ -28,12 +28,15 @@
# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
-# Colin Kong, Trent Mick, Guido van Rossum
+# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
#
# History:
#
# <see CVS and SVN checkin messages for history>
#
+# 1.0.6 - added linux_distribution()
+# 1.0.5 - fixed Java support to allow running the module on Jython
+# 1.0.4 - added IronPython support
# 1.0.3 - added normalization of Windows system name
# 1.0.2 - added more Windows support
# 1.0.1 - reformatted to make doc.py happy
@@ -88,7 +91,7 @@
__copyright__ = """
Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:ma...@le...
- Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:in...@eg...
+ Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:in...@eg...
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby granted,
@@ -107,7 +110,7 @@
"""
-__version__ = '1.0.4'
+__version__ = '1.0.6'
import sys,string,os,re
@@ -136,6 +139,11 @@
The file is read and scanned in chunks of chunksize bytes.
"""
+ if hasattr(os.path, 'realpath'):
+ # Python 2.2 introduced os.path.realpath(); it is used
+ # here to work around problems with Cygwin not being
+ # able to open symlinks for reading
+ executable = os.path.realpath(executable)
f = open(executable,'rb')
binary = f.read(chunksize)
pos = 0
@@ -218,21 +226,90 @@
return distname,version,id
_release_filename = re.compile(r'(\w+)[-_](release|version)')
-_release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?')
+_lsb_release_version = re.compile(r'(.+)'
+ ' release '
+ '([\d.]+)'
+ '[^(]*(?:\((.+)\))?')
+_release_version = re.compile(r'([^0-9]+)'
+ '(?: release )?'
+ '([\d.]+)'
+ '[^(]*(?:\((.+)\))?')
-# Note:In supported_dists below we need 'fedora' before 'redhat' as in
-# Fedora redhat-release is a link to fedora-release.
+# See also http://www.novell.com/coolsolutions/feature/11251.html
+# and http://linuxmafia.com/faq/Admin/release-files.html
+# and http://data.linux-ntfs.org/rpm/whichrpm
+# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
-def dist(distname='',version='',id='',
+_supported_dists = (
+ 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
+ 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
+ 'UnitedLinux', 'turbolinux')
- supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')):
+def _parse_release_file(firstline):
+ # Default to empty 'version' and 'id' strings. Both defaults are used
+ # when 'firstline' is empty. 'id' defaults to empty when an id can not
+ # be deduced.
+ version = ''
+ id = ''
+
+ # Parse the first line
+ m = _lsb_release_version.match(firstline)
+ if m is not None:
+ # LSB format: "distro release x.x (codename)"
+ return tuple(m.groups())
+
+ # Pre-LSB format: "distro x.x (codename)"
+ m = _release_version.match(firstline)
+ if m is not None:
+ return tuple(m.groups())
+
+ # Unkown format... take the first two words
+ l = string.split(string.strip(firstline))
+ if l:
+ version = l[0]
+ if len(l) > 1:
+ id = l[1]
+ return '', version, id
+
+def _test_parse_release_file():
+
+ for input, output in (
+ # Examples of release file contents:
+ ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64'))
+ ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64'))
+ ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586'))
+ ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux'))
+ ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche'))
+ ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike'))
+ ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant'))
+ ('CentOS release 4', ('CentOS', '4', None))
+ ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia'))
+ ):
+ parsed = _parse_release_file(input)
+ if parsed != output:
+ print (input, parsed)
+
+def linux_distribution(distname='', version='', id='',
+
+ supported_dists=_supported_dists,
+ full_distribution_name=1):
+
""" Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
suitable files are found.
+ supported_dists may be given to define the set of Linux
+ distributions to look for. It defaults to a list of currently
+ supported Linux distributions identified by their release file
+ name.
+
+ If full_distribution_name is true (default), the full
+ distribution read from the OS is returned. Otherwise the short
+ name taken from supported_dists is used.
+
Returns a tuple (distname,version,id) which default to the
args given as parameters.
@@ -242,34 +319,51 @@
except os.error:
# Probably not a Unix system
return distname,version,id
+ etc.sort()
for file in etc:
m = _release_filename.match(file)
- if m:
+ if m is not None:
_distname,dummy = m.groups()
if _distname in supported_dists:
distname = _distname
break
else:
return _dist_try_harder(distname,version,id)
- f = open('/etc/'+file,'r')
+
+ # Read the first line
+ f = open('/etc/'+file, 'r')
firstline = f.readline()
f.close()
- m = _release_version.search(firstline)
- if m:
- _version,_id = m.groups()
- if _version:
- version = _version
- if _id:
- id = _id
- else:
- # Unkown format... take the first two words
- l = string.split(string.strip(firstline))
- if l:
- version = l[0]
- if len(l) > 1:
- id = l[1]
- return distname,version,id
+ _distname, _version, _id = _parse_release_file(firstline)
+ if _distname and full_distribution_name:
+ distname = _distname
+ if _version:
+ version = _version
+ if _id:
+ id = _id
+ return distname, version, id
+
+# To maintain backwards compatibility:
+
+def dist(distname='',version='',id='',
+
+ supported_dists=_supported_dists):
+
+ """ Tries to determine the name of the Linux OS distribution name.
+
+ The function first looks for a distribution release file in
+ /etc and then reverts to _dist_try_harder() in case no
+ suitable files are found.
+
+ Returns a tuple (distname,version,id) which default to the
+ args given as parameters.
+
+ """
+ return linux_distribution(distname, version, id,
+ supported_dists=supported_dists,
+ full_distribution_name=0)
+
class _popen:
""" Fairly portable (alternative) popen implementation.
@@ -357,7 +451,7 @@
else:
return popen(cmd,mode,bufsize)
-def _norm_version(version,build=''):
+def _norm_version(version, build=''):
""" Normalize the version and build strings and return a single
version string using the format major.minor.build (or patchlevel).
@@ -378,7 +472,7 @@
'.*'
'Version ([\d.]+))')
-def _syscmd_ver(system='',release='',version='',
+def _syscmd_ver(system='', release='', version='',
supported_platforms=('win32','win16','dos','os2')):
@@ -418,7 +512,7 @@
# Parse the output
info = string.strip(info)
m = _ver_output.match(info)
- if m:
+ if m is not None:
system,release,version = m.groups()
# Strip trailing dots from version and release
if release[-1] == '.':
@@ -437,8 +531,14 @@
In case this fails, default is returned.
"""
- from win32api import RegQueryValueEx
try:
+ # Use win32api if available
+ from win32api import RegQueryValueEx
+ except ImportError:
+ # On Python 2.0 and later, emulate using _winreg
+ import _winreg
+ RegQueryValueEx = _winreg.QueryValueEx
+ try:
return RegQueryValueEx(key,name)
except:
return default
@@ -457,9 +557,9 @@
means the OS version uses debugging code, i.e. code that
checks arguments, ranges, etc. (Thomas Heller).
- Note: this function only works if Mark Hammond's win32
- package is installed and obviously only runs on Win32
- compatible platforms.
+ Note: this function works best with Mark Hammond's win32
+ package installed, but also on Python 2.3 and later. It
+ obviously only runs on Win32 compatible platforms.
"""
# XXX Is there any way to find out the processor type on WinXX ?
@@ -473,17 +573,42 @@
# Import the needed APIs
try:
import win32api
+ from win32api import RegQueryValueEx, RegOpenKeyEx, \
+ RegCloseKey, GetVersionEx
+ from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
+ VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
except ImportError:
- return release,version,csd,ptype
- from win32api import RegQueryValueEx,RegOpenKeyEx,RegCloseKey,GetVersionEx
- from win32con import HKEY_LOCAL_MACHINE,VER_PLATFORM_WIN32_NT,\
- VER_PLATFORM_WIN32_WINDOWS
+ # Emulate the win32api module using Python APIs
+ try:
+ sys.getwindowsversion
+ except AttributeError:
+ # No emulation possible, so return the defaults...
+ return release,version,csd,ptype
+ else:
+ # Emulation using _winreg (added in Python 2.0) and
+ # sys.getwindowsversion() (added in Python 2.3)
+ import _winreg
+ GetVersionEx = sys.getwindowsversion
+ RegQueryValueEx = _winreg.QueryValueEx
+ RegOpenKeyEx = _winreg.OpenKeyEx
+ RegCloseKey = _winreg.CloseKey
+ HKEY_LOCAL_MACHINE = _winreg.HKEY_LOCAL_MACHINE
+ VER_PLATFORM_WIN32_WINDOWS = 1
+ VER_PLATFORM_WIN32_NT = 2
+ VER_NT_WORKSTATION = 1
+ VER_NT_SERVER = 3
+ REG_SZ = 1
# Find out the registry key and some general version infos
- maj,min,buildno,plat,csd = GetVersionEx()
+ winver = GetVersionEx()
+ maj,min,buildno,plat,csd = winver
version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
- if csd[:13] == 'Service Pack ':
- csd = 'SP' + csd[13:]
+ if hasattr(winver, "service_pack"):
+ if winver.service_pack != "":
+ csd = 'SP%s' % winver.service_pack_major
+ else:
+ if csd[:13] == 'Service Pack ':
+ csd = 'SP' + csd[13:]
if plat == VER_PLATFORM_WIN32_WINDOWS:
regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
# Try to guess the release name
@@ -511,6 +636,36 @@
release = '2003Server'
else:
release = 'post2003'
+ elif maj == 6:
+ if hasattr(winver, "product_type"):
+ product_type = winver.product_type
+ else:
+ product_type = VER_NT_WORKSTATION
+ # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
+ # or help from the registry, we cannot properly identify
+ # non-workstation versions.
+ try:
+ key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
+ name, type = RegQueryValueEx(key, "ProductName")
+ # Discard any type that isn't REG_SZ
+ if type == REG_SZ and name.find("Server") != -1:
+ product_type = VER_NT_SERVER
+ except WindowsError:
+ # Use default of VER_NT_WORKSTATION
+ pass
+
+ if min == 0:
+ if product_type == VER_NT_WORKSTATION:
+ release = 'Vista'
+ else:
+ release = '2008Server'
+ elif min == 1:
+ if product_type == VER_NT_WORKSTATION:
+ release = '7'
+ else:
+ release = '2008ServerR2'
+ else:
+ release = 'post2008Server'
else:
if not release:
# E.g. Win3.1 with win32s
@@ -519,9 +674,9 @@
# Open the registry key
try:
- keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey)
+ keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
# Get a value to make sure the key exists...
- RegQueryValueEx(keyCurVer,'SystemRoot')
+ RegQueryValueEx(keyCurVer, 'SystemRoot')
except:
return release,version,csd,ptype
@@ -562,30 +717,22 @@
return hex(bcd)[2:]
-def mac_ver(release='',versioninfo=('','',''),machine=''):
-
- """ Get MacOS version information and return it as tuple (release,
- versioninfo, machine) with versioninfo being a tuple (version,
- dev_stage, non_release_version).
-
- Entries which cannot be determined are set to the paramter values
- which default to ''. All tuple entries are strings.
-
+def _mac_ver_gestalt():
+ """
Thanks to Mark R. Levinson for mailing documentation links and
code examples for this function. Documentation for the
gestalt() API is available online at:
http://www.rgaros.nl/gestalt/
-
"""
# Check whether the version info module is available
try:
import gestalt
import MacOS
except ImportError:
- return release,versioninfo,machine
+ return None
# Get the infos
- sysv,sysu,sysa = _mac_ver_lookup(('sysv','sysu','sysa'))
+ sysv,sysa = _mac_ver_lookup(('sysv','sysa'))
# Decode the infos
if sysv:
major = (sysv & 0xFF00) >> 8
@@ -602,32 +749,70 @@
release = '%i.%i.%i' %(major, minor, patch)
else:
release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
- if sysu:
- major = int((sysu & 0xFF000000L) >> 24)
- minor = (sysu & 0x00F00000) >> 20
- bugfix = (sysu & 0x000F0000) >> 16
- stage = (sysu & 0x0000FF00) >> 8
- nonrel = (sysu & 0x000000FF)
- version = '%s.%i.%i' % (_bcd2str(major),minor,bugfix)
- nonrel = _bcd2str(nonrel)
- stage = {0x20:'development',
- 0x40:'alpha',
- 0x60:'beta',
- 0x80:'final'}.get(stage,'')
- versioninfo = (version,stage,nonrel)
+
if sysa:
machine = {0x1: '68k',
0x2: 'PowerPC',
0xa: 'i386'}.get(sysa,'')
+
return release,versioninfo,machine
+def _mac_ver_xml():
+ fn = '/System/Library/CoreServices/SystemVersion.plist'
+ if not os.path.exists(fn):
+ return None
+
+ try:
+ import plistlib
+ except ImportError:
+ return None
+
+ pl = plistlib.readPlist(fn)
+ release = pl['ProductVersion']
+ versioninfo=('', '', '')
+ machine = os.uname()[4]
+ if machine in ('ppc', 'Power Macintosh'):
+ # for compatibility with the gestalt based code
+ machine = 'PowerPC'
+
+ return release,versioninfo,machine
+
+
+def mac_ver(release='',versioninfo=('','',''),machine=''):
+
+ """ Get MacOS version information and return it as tuple (release,
+ versioninfo, machine) with versioninfo being a tuple (version,
+ dev_stage, non_release_version).
+
+ Entries which cannot be determined are set to the paramter values
+ which default to ''. All tuple entries are strings.
+ """
+
+ # First try reading the information from an XML file which should
+ # always be present
+ info = _mac_ver_xml()
+ if info is not None:
+ return info
+
+ # If that doesn't work for some reason fall back to reading the
+ # information using gestalt calls.
+ info = _mac_ver_gestalt()
+ if info is not None:
+ return info
+
+ # If that also doesn't work return the default values
+ return release,versioninfo,machine
+
def _java_getprop(name,default):
from java.lang import System
from org.python.core.Py import newString
try:
- return newString(System.getProperty(name))
- except:
+ value = System.getProperty(name)
+ if value is None:
+ return default
+ return newString(value)
+ except AttributeError:
return default
def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
@@ -648,20 +833,20 @@
except ImportError:
return release,vendor,vminfo,osinfo
- vendor = _java_getprop('java.vendor',vendor)
- release = _java_getprop('java.version',release)
- vm_name,vm_release,vm_vendor = vminfo
- vm_name = _java_getprop('java.vm.name',vm_name)
- vm_vendor = _java_getprop('java.vm.vendor',vm_vendor)
- vm_release = _java_getprop('java.vm.version',vm_release)
- vminfo = vm_name,vm_release,vm_vendor
- os_name,os_version,os_arch = osinfo
- os_arch = _java_getprop('os.arch',os_arch)
- os_name = _java_getprop('os.name',os_name)
- os_version = _java_getprop('os.version',os_version)
- osinfo = os_name,os_version,os_arch
+ vendor = _java_getprop('java.vendor', vendor)
+ release = _java_getprop('java.version', release)
+ vm_name, vm_release, vm_vendor = vminfo
+ vm_name = _java_getprop('java.vm.name', vm_name)
+ vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
+ vm_release = _java_getprop('java.vm.version', vm_release)
+ vminfo = vm_name, vm_release, vm_vendor
+ os_name, os_version, os_arch = osinfo
+ os_arch = _java_getprop('os.arch', os_arch)
+ os_name = _java_getprop('os.name', os_name)
+ os_version = _java_getprop('os.version', os_version)
+ osinfo = os_name, os_version, os_arch
- return release,vendor,vminfo,osinfo
+ return release, vendor, vminfo, osinfo
### System name aliasing
@@ -727,7 +912,7 @@
# Format the platform string
platform = string.join(
map(string.strip,
- filter(len,args)),
+ filter(len, args)),
'-')
# Cleanup some possible filename obstacles...
@@ -825,9 +1010,12 @@
case the command should fail.
"""
- target = _follow_symlinks(target)
+ if sys.platform in ('dos','win32','win16','os2'):
+ # XXX Others too ?
+ return default
+ target = _follow_symlinks(target).replace('"', '\\"')
try:
- f = os.popen('file %s 2> /dev/null' % target)
+ f = os.popen('file "%s" 2> /dev/null' % target)
except (AttributeError,os.error):
return default
output = string.strip(f.read())
@@ -882,19 +1070,22 @@
bits = str(size*8) + 'bit'
# Get data from the 'file' system command
- output = _syscmd_file(executable,'')
+ if executable:
+ output = _syscmd_file(executable, '')
+ else:
+ output = ''
if not output and \
executable == sys.executable:
# "file" command did not return anything; we'll try to provide
# some sensible defaults then...
- if _default_architecture.has_key(sys.platform):
- b,l = _default_architecture[sys.platform]
+ if sys.platform in _default_architecture:
+ b, l = _default_architecture[sys.platform]
if b:
bits = b
if l:
linkage = l
- return bits,linkage
+ return bits, linkage
# Split the output into a list of strings omitting the filename
fileout = _architecture_split(output)[1:]
@@ -948,29 +1139,44 @@
"""
global _uname_cache
+ no_os_uname = 0
if _uname_cache is not None:
return _uname_cache
+ processor = ''
+
# Get some infos from the builtin os.uname API...
try:
system,node,release,version,machine = os.uname()
-
except AttributeError:
- # Hmm, no uname... we'll have to poke around the system then.
- system = sys.platform
- release = ''
- version = ''
- node = _node()
- machine = ''
- processor = ''
- use_syscmd_ver = 1
+ no_os_uname = 1
+ if no_os_uname or not filter(None, (system, node, release, version, machine)):
+ # Hmm, no there is either no uname or uname has returned
+ #'unknowns'... we'll have to poke around the system then.
+ if no_os_uname:
+ system = sys.platform
+ release = ''
+ version = ''
+ node = _node()
+ machine = ''
+
+ use_syscmd_ver = 01
+
# Try win32_ver() on win32 platforms
if system == 'win32':
release,version,csd,ptype = win32_ver()
if release and version:
use_syscmd_ver = 0
+ # Try to use the PROCESSOR_* environment variables
+ # available on Win XP and later; see
+ # http://support.microsoft.com/kb/888731 and
+ # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
+ if not machine:
+ machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
+ if not processor:
+ processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
# Try the 'ver' system command available on some
# platforms
@@ -980,6 +1186,16 @@
# (_syscmd_ver() tends to return the vendor name as well)
if system == 'Microsoft Windows':
system = 'Windows'
+ elif system == 'Microsoft' and release == 'Windows':
+ # Under Windows Vista and Windows Server 2008,
+ # Microsoft changed the output of the ver command. The
+ # release is no longer printed. This causes the
+ # system and release to be misidentified.
+ system = 'Windows'
+ if '6.0' == version[:3]:
+ release = 'Vista'
+ else:
+ release = ''
# In case we still don't know anything useful, we'll try to
# help ourselves
@@ -1002,30 +1218,28 @@
release,(version,stage,nonrel),machine = mac_ver()
system = 'MacOS'
- else:
- # System specific extensions
- if system == 'OpenVMS':
- # OpenVMS seems to have release and version mixed up
- if not release or release == '0':
- release = version
- version = ''
- # Get processor information
- try:
- import vms_lib
- except ImportError:
- pass
+ # System specific extensions
+ if system == 'OpenVMS':
+ # OpenVMS seems to have release and version mixed up
+ if not release or release == '0':
+ release = version
+ version = ''
+ # Get processor information
+ try:
+ import vms_lib
+ except ImportError:
+ pass
+ else:
+ csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
+ if (cpu_number >= 128):
+ processor = 'Alpha'
else:
- csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
- if (cpu_number >= 128):
- processor = 'Alpha'
- else:
- processor = 'VAX'
- else:
- # Get processor information from the uname system command
- processor = _syscmd_uname('-p','')
+ processor = 'VAX'
+ if not processor:
+ # Get processor information from the uname system command
+ processor = _syscmd_uname('-p','')
- # 'unknown' is not really any useful as information; we'll convert
- # it to '' which is more portable
+ #If any unknowns still exist, replace them with ''s, which are more portable
if system == 'unknown':
system = ''
if node == 'unknown':
@@ -1109,37 +1323,137 @@
### Various APIs for extracting information from sys.version
-_sys_version_parser = re.compile(r'([\w.+]+)\s*'
- '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
- '\[([^\]]+)\]?')
-_sys_version_cache = None
+_sys_version_parser = re.compile(
+ r'([\w.+]+)\s*'
+ '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
+ '\[([^\]]+)\]?')
-def _sys_version():
+_jython_sys_version_parser = re.compile(
+ r'([\d\.]+)')
+_ironpython_sys_version_parser = re.compile(
+ r'IronPython\s*'
+ '([\d\.]+)'
+ '(?: \(([\d\.]+)\))?'
+ ' on (.NET [\d\.]+)')
+
+_sys_version_cache = {}
+
+def _sys_version(sys_version=None):
+
""" Returns a parsed version of Python's sys.version as tuple
- (version, buildno, builddate, compiler) referring to the Python
- version, build number, build date/time as string and the compiler
+ (name, version, branch, revision, buildno, builddate, compiler)
+ referring to the Python implementation name, version, branch,
+ revision, build number, build date/time as string and the compiler
identification string.
Note that unlike the Python sys.version, the returned value
for the Python version will always include the patchlevel (it
defaults to '.0').
+ The function returns empty strings for tuple entries that
+ cannot be determined.
+
+ sys_version may be given to parse an alternative version
+ string, e.g. if the version was read from a different Python
+ interpreter.
+
"""
- global _sys_version_cache
+ # Get the Python version
+ if sys_version is None:
+ sys_version = sys.version
- if _sys_version_cache is not None:
- return _sys_version_cache
- version, buildno, builddate, buildtime, compiler = \
- _sys_version_parser.match(sys.version).groups()
- builddate = builddate + ' ' + buildtime
+ # Try the cache first
+ result = _sys_version_cache.get(sys_version, None)
+ if result is not None:
+ return result
+
+ # Parse it
+ if sys_version[:10] == 'IronPython':
+ # IronPython
+ name = 'IronPython'
+ match = _ironpython_sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse IronPython sys.version: %s' %
+ repr(sys_version))
+ version, alt_version, compiler = match.groups()
+ branch = ''
+ revision = ''
+ buildno = ''
+ builddate = ''
+
+ elif sys.platform[:4] == 'java':
+ # Jython
+ name = 'Jython'
+ match = _jython_sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse Jython sys.version: %s' %
+ repr(sys_version))
+ version, = match.groups()
+ branch = ''
+ revision = ''
+ compiler = sys.platform
+ buildno = ''
+ builddate = ''
+
+ else:
+ # CPython
+ match = _sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse CPython sys.version: %s' %
+ repr(sys_version))
+ version, buildno, builddate, buildtime, compiler = \
+ match.groups()
+ if hasattr(sys, 'subversion'):
+ # sys.subversion was added in Python 2.5
+ name, branch, revision = sys.subversion
+ else:
+ name = 'CPython'
+ branch = ''
+ revision = ''
+ builddate = builddate + ' ' + buildtime
+
+ # Add the patchlevel version if missing
l = string.split(version, '.')
if len(l) == 2:
l.append('0')
version = string.join(l, '.')
- _sys_version_cache = (version, buildno, builddate, compiler)
- return _sys_version_cache
+ # Build and cache the result
+ result = (name, version, branch, revision, buildno, builddate, compiler)
+ _sys_version_cache[sys_version] = result
+ return result
+
+def _test_sys_version():
+
+ _sys_version_cache.clear()
+ for input, output in (
+ ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
+ ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
+ ('IronPython 1.0.60816 on .NET 2.0.50727.42',
+ ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')),
+ ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42',
+ ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')),
+ ):
+ parsed = _sys_version(input)
+ if parsed != output:
+ print (input, parsed)
+
+def python_implementation():
+
+ """ Returns a string identifying the Python implementation.
+
+ Currently, the following implementations are identified:
+ 'CPython' (C implementation of Python),
+ 'IronPython' (.NET implementation of Python),
+ 'Jython' (Java implementation of Python).
+
+ """
+ return _sys_version()[0]
+
def python_version():
""" Returns the Python version as string 'major.minor.patchlevel'
@@ -1148,7 +1462,7 @@
will always include the patchlevel (it defaults to 0).
"""
- return _sys_version()[0]
+ return _sys_version()[1]
def python_version_tuple():
@@ -1159,15 +1473,42 @@
will always include the patchlevel (it defaults to 0).
"""
- return string.split(_sys_version()[0], '.')
+ return tuple(string.split(_sys_version()[1], '.'))
+def python_branch():
+
+ """ Returns a string identifying the Python implementation
+ branch.
+
+ For CPython this is the Subversion branch from which the
+ Python binary was built.
+
+ If not available, an empty string is returned.
+
+ """
+
+ return _sys_version()[2]
+
+def python_revision():
+
+ """ Returns a string identifying the Python implementation
+ revision.
+
+ For CPython this is the Subversion revision from which the
+ Python binary was built.
+
+ If not available, an empty string is returned.
+
+ """
+ return _sys_version()[3]
+
def python_build():
""" Returns a tuple (buildno, builddate) stating the Python
build number and date as strings.
"""
- return _sys_version()[1:3]
+ return _sys_version()[4:6]
def python_compiler():
@@ -1175,7 +1516,7 @@
Python.
"""
- return _sys_version()[3]
+ return _sys_version()[6]
### The Opus Magnum of platform strings :-)
@@ -1236,7 +1577,7 @@
elif system == 'Java':
# Java platforms
r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
- if terse:
+ if terse or not os_name:
platform = _platform(system,release,version)
else:
platform = _platform(system,release,version,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-22 02:38:23
|
Revision: 7261
http://jython.svn.sourceforge.net/jython/?rev=7261&view=rev
Author: pjenvey
Date: 2011-03-22 02:38:16 +0000 (Tue, 22 Mar 2011)
Log Message:
-----------
coding standards and other minor changes
Modified Paths:
--------------
trunk/jython/src/org/python/core/PyInstance.java
trunk/jython/src/org/python/core/PyInteger.java
trunk/jython/src/org/python/core/PyLong.java
trunk/jython/src/org/python/core/PyObject.java
trunk/jython/src/org/python/core/PyString.java
trunk/jython/src/org/python/core/__builtin__.java
trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java
trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java
trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java
trunk/jython/src/org/python/core/stringlib/MarkupIterator.java
Modified: trunk/jython/src/org/python/core/PyInstance.java
===================================================================
--- trunk/jython/src/org/python/core/PyInstance.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/PyInstance.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -788,16 +788,17 @@
}
@Override
- public PyObject __format__(PyObject format_spec) {
- return instance___format__(format_spec);
+ public PyObject __format__(PyObject formatSpec) {
+ return instance___format__(formatSpec);
}
@ExposedMethod
- final PyObject instance___format__(PyObject format_spec) {
+ final PyObject instance___format__(PyObject formatSpec) {
PyObject func = __findattr__("__format__");
- if (func == null)
- return super.__format__(format_spec);
- return func.__call__(format_spec);
+ if (func == null) {
+ return super.__format__(formatSpec);
+ }
+ return func.__call__(formatSpec);
}
// Generated by make_binops.py
Modified: trunk/jython/src/org/python/core/PyInteger.java
===================================================================
--- trunk/jython/src/org/python/core/PyInteger.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/PyInteger.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -914,31 +914,30 @@
}
@Override
- public PyObject __format__(PyObject format_spec) {
- return int___format__(format_spec);
+ public PyObject __format__(PyObject formatSpec) {
+ return int___format__(formatSpec);
}
@ExposedMethod(doc = BuiltinDocs.int___format___doc)
- final PyObject int___format__(PyObject format_spec) {
- return formatImpl(getValue(), format_spec);
+ final PyObject int___format__(PyObject formatSpec) {
+ return formatImpl(getValue(), formatSpec);
}
- static PyObject formatImpl(Object value, PyObject format_spec) {
- if (format_spec instanceof PyString) {
- String result;
- try {
- String specString = ((PyString) format_spec).getString();
- InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
- result = formatIntOrLong(value, spec);
- } catch (IllegalArgumentException e) {
- throw Py.ValueError(e.getMessage());
- }
- if (format_spec instanceof PyUnicode) {
- return new PyUnicode(result);
- }
- return new PyString(result);
+ static PyObject formatImpl(Object value, PyObject formatSpec) {
+ if (!(formatSpec instanceof PyString)) {
+ throw Py.TypeError("__format__ requires str or unicode");
}
- throw Py.TypeError("__format__ requires str or unicode");
+
+ PyString formatSpecStr = (PyString) formatSpec;
+ String result;
+ try {
+ String specString = formatSpecStr.getString();
+ InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
+ result = formatIntOrLong(value, spec);
+ } catch (IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ return formatSpecStr.createInstance(result);
}
/**
@@ -956,15 +955,14 @@
if (value instanceof Integer) {
int intValue = (Integer) value;
sign = intValue < 0 ? -1 : intValue == 0 ? 0 : 1;
- }
- else {
+ } else {
sign = ((BigInteger) value).signum();
}
String strValue;
if (spec.type == 'c') {
if (spec.sign != '\0') {
- throw new IllegalArgumentException("Sign not allowed with " +
- "integer format specifier 'c'");
+ throw new IllegalArgumentException("Sign not allowed with integer format "
+ + "specifier 'c'");
}
if (value instanceof Integer) {
int intValue = (Integer) value;
@@ -972,8 +970,7 @@
throw new IllegalArgumentException("%c arg not in range(0x10000)");
}
strValue = Character.toString((char) intValue);
- }
- else {
+ } else {
BigInteger bigInt = (BigInteger) value;
if (bigInt.intValue() > 0xffff || bigInt.bitCount() > 16) {
throw new IllegalArgumentException("%c arg not in range(0x10000)");
@@ -993,18 +990,18 @@
// TODO locale-specific formatting for 'n'
if (value instanceof BigInteger) {
strValue = ((BigInteger) value).toString(radix);
- }
- else {
+ } else {
strValue = Integer.toString((Integer) value, radix);
}
if (spec.alternate) {
- if (radix == 2)
+ if (radix == 2) {
strValue = "0b" + strValue;
- else if (radix == 8)
+ } else if (radix == 8) {
strValue = "0o" + strValue;
- else if (radix == 16)
+ } else if (radix == 16) {
strValue = "0x" + strValue;
+ }
}
if (spec.type == 'X') {
strValue = strValue.toUpperCase();
Modified: trunk/jython/src/org/python/core/PyLong.java
===================================================================
--- trunk/jython/src/org/python/core/PyLong.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/PyLong.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -982,13 +982,13 @@
}
@Override
- public PyObject __format__(PyObject format_spec) {
- return long___format__(format_spec);
+ public PyObject __format__(PyObject formatSpec) {
+ return long___format__(formatSpec);
}
@ExposedMethod(doc = BuiltinDocs.long___format___doc)
- final PyObject long___format__(PyObject format_spec) {
- return PyInteger.formatImpl(getValue(), format_spec);
+ final PyObject long___format__(PyObject formatSpec) {
+ return PyInteger.formatImpl(getValue(), formatSpec);
}
@Override
Modified: trunk/jython/src/org/python/core/PyObject.java
===================================================================
--- trunk/jython/src/org/python/core/PyObject.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/PyObject.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -1710,14 +1710,13 @@
return false;
}
- public PyObject __format__(PyObject format_spec) {
- return object___format__(format_spec);
+ public PyObject __format__(PyObject formatSpec) {
+ return object___format__(formatSpec);
}
@ExposedMethod(doc = BuiltinDocs.object___format___doc)
- final PyObject object___format__(PyObject format_spec) {
- PyString str = __str__();
- return str.__format__(format_spec);
+ final PyObject object___format__(PyObject formatSpec) {
+ return __str__().__format__(formatSpec);
}
/**
Modified: trunk/jython/src/org/python/core/PyString.java
===================================================================
--- trunk/jython/src/org/python/core/PyString.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/PyString.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -2533,7 +2533,7 @@
final PyObject str_format(PyObject[] args, String[] keywords) {
try {
return new PyString(buildFormattedString(getString(), args, keywords));
- } catch(IllegalArgumentException e) {
+ } catch (IllegalArgumentException e) {
throw Py.ValueError(e.getMessage());
}
}
@@ -2562,11 +2562,9 @@
}
if ("r".equals(chunk.conversion)) {
fieldObj = fieldObj.__repr__();
- }
- else if ("s".equals(chunk.conversion)) {
+ } else if ("s".equals(chunk.conversion)) {
fieldObj = fieldObj.__str__();
- }
- else if (chunk.conversion != null) {
+ } else if (chunk.conversion != null) {
throw Py.ValueError("Unknown conversion specifier " + chunk.conversion);
}
String formatSpec = chunk.formatSpec;
@@ -2581,17 +2579,17 @@
Object head = iterator.head();
PyObject obj = null;
int positionalCount = args.length - keywords.length;
+
if (head instanceof Integer) {
int index = (Integer) head;
if (index >= positionalCount) {
throw Py.IndexError("tuple index out of range");
}
obj = args[index];
- }
- else {
+ } else {
for (int i = 0; i < keywords.length; i++) {
if (keywords[i].equals(head)) {
- obj = args[positionalCount+i];
+ obj = args[positionalCount + i];
break;
}
}
@@ -2607,14 +2605,15 @@
}
if (chunk.is_attr) {
obj = obj.__getattr__((String) chunk.value);
- }
- else {
+ } else {
PyObject key = chunk.value instanceof String
? new PyString((String) chunk.value)
: new PyInteger((Integer) chunk.value);
obj = obj.__getitem__(key);
}
- if (obj == null) break;
+ if (obj == null) {
+ break;
+ }
}
}
return obj;
@@ -2626,27 +2625,26 @@
}
@Override
- public PyObject __format__(PyObject format_spec) {
- return str___format__(format_spec);
+ public PyObject __format__(PyObject formatSpec) {
+ return str___format__(formatSpec);
}
@ExposedMethod(doc = BuiltinDocs.str___format___doc)
- final PyObject str___format__(PyObject format_spec) {
- if (format_spec instanceof PyString) {
- String result;
- try {
- String specString = ((PyString) format_spec).getString();
- InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
- result = formatString(getString(), spec);
- } catch (IllegalArgumentException e) {
- throw Py.ValueError(e.getMessage());
- }
- if (format_spec instanceof PyUnicode) {
- return new PyUnicode(result);
- }
- return new PyString(result);
+ final PyObject str___format__(PyObject formatSpec) {
+ if (!(formatSpec instanceof PyString)) {
+ throw Py.TypeError("__format__ requires str or unicode");
}
- throw Py.TypeError("__format__ requires str or unicode");
+
+ PyString formatSpecStr = (PyString) formatSpec;
+ String result;
+ try {
+ String specString = formatSpecStr.getString();
+ InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
+ result = formatString(getString(), spec);
+ } catch (IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ return formatSpecStr.createInstance(result);
}
/**
Modified: trunk/jython/src/org/python/core/__builtin__.java
===================================================================
--- trunk/jython/src/org/python/core/__builtin__.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/__builtin__.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -1314,7 +1314,7 @@
@Override
public PyObject __call__(PyObject arg1) {
- return __call__(arg1, new PyString(""));
+ return __call__(arg1, Py.EmptyString);
}
@Override
Modified: trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -1,6 +1,11 @@
package org.python.core.stringlib;
-import org.python.core.*;
+import org.python.core.PyBoolean;
+import org.python.core.PyInteger;
+import org.python.core.PyObject;
+import org.python.core.PyString;
+import org.python.core.PyTuple;
+import org.python.core.PyType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -9,6 +14,9 @@
*/
@ExposedType(name = "fieldnameiterator", base = PyObject.class, isBaseType = false)
public class FieldNameIterator extends PyObject {
+
+ public static final PyType TYPE = PyType.fromClass(FieldNameIterator.class);
+
private String markup;
private Object head;
private int index;
@@ -26,15 +34,21 @@
@Override
public PyObject __iter__() {
- return this;
+ return fieldnameiterator___iter__();
}
@ExposedMethod
- public PyObject fieldnameiterator___iter__() {
+ final PyObject fieldnameiterator___iter__() {
return this;
}
+ @Override
public PyObject __iternext__() {
+ return fieldnameiterator___iternext__();
+ }
+
+ @ExposedMethod
+ final PyObject fieldnameiterator___iternext__() {
Chunk chunk = nextChunk();
if (chunk == null) {
return null;
@@ -43,23 +57,21 @@
elements [0] = new PyBoolean(chunk.is_attr);
if (chunk.value instanceof Integer) {
elements [1] = new PyInteger((Integer) chunk.value);
- }
- else {
+ } else {
elements [1] = new PyString((String) chunk.value);
}
return new PyTuple(elements);
}
- @ExposedMethod
- public PyObject fieldnameiterator___iternext__() {
- return __iternext__();
- }
-
private int nextDotOrBracket(String markup) {
int dotPos = markup.indexOf('.', index);
- if (dotPos < 0) dotPos = markup.length();
+ if (dotPos < 0) {
+ dotPos = markup.length();
+ }
int bracketPos = markup.indexOf('[', index);
- if (bracketPos < 0) bracketPos = markup.length();
+ if (bracketPos < 0) {
+ bracketPos = markup.length();
+ }
return Math.min(dotPos, bracketPos);
}
@@ -74,8 +86,7 @@
Chunk chunk = new Chunk();
if (markup.charAt(index) == '[') {
parseItemChunk(chunk);
- }
- else if (markup.charAt(index) == '.') {
+ } else if (markup.charAt(index) == '.') {
parseAttrChunk(chunk);
}
return chunk;
@@ -87,7 +98,7 @@
if (endBracket < 0) {
throw new IllegalArgumentException("Missing ']' in format string");
}
- String itemValue = markup.substring(index+1, endBracket);
+ String itemValue = markup.substring(index + 1, endBracket);
if (itemValue.length() == 0) {
throw new IllegalArgumentException("Empty attribute in format string");
}
@@ -96,7 +107,7 @@
} catch (NumberFormatException e) {
chunk.value = itemValue;
}
- index = endBracket+1;
+ index = endBracket + 1;
}
private void parseAttrChunk(Chunk chunk) {
@@ -112,6 +123,7 @@
public static class Chunk {
public boolean is_attr;
- public Object value; // Integer or String
+ /** Integer or String. */
+ public Object value;
}
}
Modified: trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -25,8 +25,7 @@
}
if (useAlign == '^') {
leading = remaining/2;
- }
- else if (useAlign == '<') {
+ } else if (useAlign == '<') {
leading = 0;
}
char fill = fill_char != 0 ? fill_char : ' ';
@@ -34,7 +33,7 @@
result.append(fill);
}
result.append(value);
- for (int i = 0; i < remaining-leading; i++) {
+ for (int i = 0; i < remaining - leading; i++) {
result.append(fill);
}
return result.toString();
Modified: trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -29,8 +29,7 @@
if (spec.length() >= 1 && isAlign(spec.charAt(0))) {
result.align = spec.charAt(index);
index++;
- }
- else if (spec.length() >= 2 && isAlign(spec.charAt(1))) {
+ } else if (spec.length() >= 2 && isAlign(spec.charAt(1))) {
result.fill_char = spec.charAt(0);
result.align = spec.charAt(1);
index += 2;
@@ -73,7 +72,9 @@
index++;
empty = false;
}
- if (empty) return -1;
+ if (empty) {
+ return -1;
+ }
return value;
}
Modified: trunk/jython/src/org/python/core/stringlib/MarkupIterator.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/MarkupIterator.java 2011-03-21 23:11:25 UTC (rev 7260)
+++ trunk/jython/src/org/python/core/stringlib/MarkupIterator.java 2011-03-22 02:38:16 UTC (rev 7261)
@@ -1,6 +1,10 @@
package org.python.core.stringlib;
-import org.python.core.*;
+import org.python.core.Py;
+import org.python.core.PyObject;
+import org.python.core.PyString;
+import org.python.core.PyTuple;
+import org.python.core.PyType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
@@ -9,6 +13,9 @@
*/
@ExposedType(name = "formatteriterator", base = PyObject.class, isBaseType = false)
public class MarkupIterator extends PyObject {
+
+ public static final PyType TYPE = PyType.fromClass(MarkupIterator.class);
+
private final String markup;
private int index;
@@ -18,15 +25,21 @@
@Override
public PyObject __iter__() {
- return this;
+ return formatteriterator___iter__();
}
@ExposedMethod
- public PyObject formatteriterator___iter__() {
+ final PyObject formatteriterator___iter__() {
return this;
}
+ @Override
public PyObject __iternext__() {
+ return formatteriterator___iternext__();
+ }
+
+ @ExposedMethod
+ final PyObject formatteriterator___iternext__() {
Chunk chunk;
try {
chunk = nextChunk();
@@ -40,36 +53,30 @@
elements[0] = new PyString(chunk.literalText);
elements[1] = new PyString(chunk.fieldName);
if (chunk.fieldName.length() > 0) {
- elements[2] = chunk.formatSpec == null ? Py.EmptyString : new PyString(chunk.formatSpec);
- }
- else {
+ elements[2] = chunk.formatSpec == null
+ ? Py.EmptyString : new PyString(chunk.formatSpec);
+ } else {
elements[2] = Py.None;
}
elements[3] = chunk.conversion == null ? Py.None : new PyString(chunk.conversion);
return new PyTuple(elements);
}
- @ExposedMethod
- public PyObject formatteriterator___iternext__() {
- return __iternext__();
- }
-
public Chunk nextChunk() {
if (index == markup.length()) {
return null;
}
Chunk result = new Chunk();
int pos = index;
- while(true) {
+ while (true) {
pos = indexOfFirst(markup, pos, '{', '}');
- if (pos >= 0 && pos < markup.length()-1 &&
- markup.charAt(pos+1) == markup.charAt(pos)) {
- pos += 2; // skip escaped bracket
- }
- else if (pos >= 0 && markup.charAt(pos) == '}') {
+ if (pos >= 0 && pos < markup.length() - 1
+ && markup.charAt(pos + 1) == markup.charAt(pos)) {
+ // skip escaped bracket
+ pos += 2;
+ } else if (pos >= 0 && markup.charAt(pos) == '}') {
throw new IllegalArgumentException("Single '}' encountered in format string");
- }
- else {
+ } else {
break;
}
}
@@ -87,8 +94,7 @@
if (markup.charAt(pos) == '{') {
count++;
result.formatSpecNeedsExpanding = true;
- }
- else if (markup.charAt(pos) == '}') {
+ } else if (markup.charAt(pos) == '}') {
count--;
if (count == 0) {
parseField(result, markup.substring(fieldStart, pos));
@@ -98,8 +104,9 @@
}
pos++;
}
- if (count > 0)
+ if (count > 0) {
throw new IllegalArgumentException("Single '{' encountered in format string");
+ }
index = pos;
}
return result;
@@ -125,14 +132,12 @@
throw new IllegalArgumentException("expected ':' " +
"after conversion specifier");
}
- result.formatSpec = fieldMarkup.substring(pos+1);
+ result.formatSpec = fieldMarkup.substring(pos + 1);
}
+ } else {
+ result.formatSpec = fieldMarkup.substring(pos + 1);
}
- else {
- result.formatSpec = fieldMarkup.substring(pos+1);
- }
- }
- else {
+ } else {
result.fieldName = fieldMarkup;
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 23:11:31
|
Revision: 7260
http://jython.svn.sourceforge.net/jython/?rev=7260&view=rev
Author: pjenvey
Date: 2011-03-21 23:11:25 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
better support for Java exceptions in writeUnraisable
Modified Paths:
--------------
trunk/jython/src/org/python/core/Py.java
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2011-03-21 23:10:49 UTC (rev 7259)
+++ trunk/jython/src/org/python/core/Py.java 2011-03-21 23:11:25 UTC (rev 7260)
@@ -1208,15 +1208,10 @@
return buf.toString();
}
- public static void writeUnraisable(Exception exc, PyObject obj) {
- if (exc instanceof PyException) {
- PyException pye = (PyException) exc;
- stderr.println(String.format("Exception %s in %s ignored",
- formatException(pye.type, pye.value, true), obj));
- } else {
- // XXX: this could be better handled
- exc.printStackTrace();
- }
+ public static void writeUnraisable(Throwable unraisable, PyObject obj) {
+ PyException pye = JavaError(unraisable);
+ stderr.println(String.format("Exception %s in %s ignored",
+ formatException(pye.type, pye.value, true), obj));
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 23:11:01
|
Revision: 7259
http://jython.svn.sourceforge.net/jython/?rev=7259&view=rev
Author: pjenvey
Date: 2011-03-21 23:10:49 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
might as well deprecate javapath so we don't really have to maintain it going
forward
Modified Paths:
--------------
trunk/jython/Lib/javapath.py
Modified: trunk/jython/Lib/javapath.py
===================================================================
--- trunk/jython/Lib/javapath.py 2011-03-21 21:57:22 UTC (rev 7258)
+++ trunk/jython/Lib/javapath.py 2011-03-21 23:10:49 UTC (rev 7259)
@@ -21,6 +21,9 @@
import os
from org.python.core.Py import newString as asPyString
+import warnings
+warnings.warn('The javapath module is deprecated. Use the os.path module.',
+ DeprecationWarning, 2)
def _tostr(s, method):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 21:57:28
|
Revision: 7258
http://jython.svn.sourceforge.net/jython/?rev=7258&view=rev
Author: pjenvey
Date: 2011-03-21 21:57:22 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
add Dmitry for his PEP 3101 implementation
Modified Paths:
--------------
trunk/jython/ACKNOWLEDGMENTS
Modified: trunk/jython/ACKNOWLEDGMENTS
===================================================================
--- trunk/jython/ACKNOWLEDGMENTS 2011-03-21 05:57:39 UTC (rev 7257)
+++ trunk/jython/ACKNOWLEDGMENTS 2011-03-21 21:57:22 UTC (rev 7258)
@@ -93,6 +93,7 @@
Costantino Cerbo
Alex Groenholm
Anselm Kruis
+ Dmitry Jemerov
Local Variables:
mode: indented-text
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 05:57:46
|
Revision: 7257
http://jython.svn.sourceforge.net/jython/?rev=7257&view=rev
Author: pjenvey
Date: 2011-03-21 05:57:39 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
a somewhat complete PEP 3101 implementation (str.format)
refs #1718
from Dmitry Jemerov @ PyCon 2011 (thanks!)
Modified Paths:
--------------
trunk/jython/CoreExposed.includes
trunk/jython/src/org/python/core/PyInstance.java
trunk/jython/src/org/python/core/PyInteger.java
trunk/jython/src/org/python/core/PyLong.java
trunk/jython/src/org/python/core/PyObject.java
trunk/jython/src/org/python/core/PyString.java
trunk/jython/src/org/python/core/__builtin__.java
Added Paths:
-----------
trunk/jython/src/org/python/core/stringlib/
trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java
trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java
trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java
trunk/jython/src/org/python/core/stringlib/MarkupIterator.java
trunk/jython/tests/java/org/python/core/StringFormatTest.java
Modified: trunk/jython/CoreExposed.includes
===================================================================
--- trunk/jython/CoreExposed.includes 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/CoreExposed.includes 2011-03-21 05:57:39 UTC (rev 7257)
@@ -44,6 +44,8 @@
org/python/core/PyType.class
org/python/core/PyUnicode.class
org/python/core/PyXRange.class
+org/python/core/stringlib/MarkupIterator.class
+org/python/core/stringlib/FieldNameIterator.class
org/python/modules/PyStruct.class
org/python/modules/PyTeeIterator.class
org/python/jsr223/PyScriptEngineScope.class
Modified: trunk/jython/src/org/python/core/PyInstance.java
===================================================================
--- trunk/jython/src/org/python/core/PyInstance.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/PyInstance.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -787,6 +787,19 @@
ret.getType().fastGetName()));
}
+ @Override
+ public PyObject __format__(PyObject format_spec) {
+ return instance___format__(format_spec);
+ }
+
+ @ExposedMethod
+ final PyObject instance___format__(PyObject format_spec) {
+ PyObject func = __findattr__("__format__");
+ if (func == null)
+ return super.__format__(format_spec);
+ return func.__call__(format_spec);
+ }
+
// Generated by make_binops.py
// Unary ops
Modified: trunk/jython/src/org/python/core/PyInteger.java
===================================================================
--- trunk/jython/src/org/python/core/PyInteger.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/PyInteger.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -7,6 +7,8 @@
import java.io.Serializable;
import java.math.BigInteger;
+import org.python.core.stringlib.InternalFormatSpec;
+import org.python.core.stringlib.InternalFormatSpecParser;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
@@ -912,6 +914,118 @@
}
@Override
+ public PyObject __format__(PyObject format_spec) {
+ return int___format__(format_spec);
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.int___format___doc)
+ final PyObject int___format__(PyObject format_spec) {
+ return formatImpl(getValue(), format_spec);
+ }
+
+ static PyObject formatImpl(Object value, PyObject format_spec) {
+ if (format_spec instanceof PyString) {
+ String result;
+ try {
+ String specString = ((PyString) format_spec).getString();
+ InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
+ result = formatIntOrLong(value, spec);
+ } catch (IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ if (format_spec instanceof PyUnicode) {
+ return new PyUnicode(result);
+ }
+ return new PyString(result);
+ }
+ throw Py.TypeError("__format__ requires str or unicode");
+ }
+
+ /**
+ * Formats an integer or long number according to a PEP-3101 format specification.
+ *
+ * @param value Integer or BigInteger object specifying the value to format.
+ * @param spec parsed PEP-3101 format specification.
+ * @return result of the formatting.
+ */
+ public static String formatIntOrLong(Object value, InternalFormatSpec spec) {
+ if (spec.precision != -1) {
+ throw new IllegalArgumentException("Precision not allowed in integer format specifier");
+ }
+ int sign;
+ if (value instanceof Integer) {
+ int intValue = (Integer) value;
+ sign = intValue < 0 ? -1 : intValue == 0 ? 0 : 1;
+ }
+ else {
+ sign = ((BigInteger) value).signum();
+ }
+ String strValue;
+ if (spec.type == 'c') {
+ if (spec.sign != '\0') {
+ throw new IllegalArgumentException("Sign not allowed with " +
+ "integer format specifier 'c'");
+ }
+ if (value instanceof Integer) {
+ int intValue = (Integer) value;
+ if (intValue > 0xffff) {
+ throw new IllegalArgumentException("%c arg not in range(0x10000)");
+ }
+ strValue = Character.toString((char) intValue);
+ }
+ else {
+ BigInteger bigInt = (BigInteger) value;
+ if (bigInt.intValue() > 0xffff || bigInt.bitCount() > 16) {
+ throw new IllegalArgumentException("%c arg not in range(0x10000)");
+ }
+ strValue = Character.toString((char) bigInt.intValue());
+ }
+ } else {
+ int radix = 10;
+ if (spec.type == 'o') {
+ radix = 8;
+ } else if (spec.type == 'x' || spec.type == 'X') {
+ radix = 16;
+ } else if (spec.type == 'b') {
+ radix = 2;
+ }
+
+ // TODO locale-specific formatting for 'n'
+ if (value instanceof BigInteger) {
+ strValue = ((BigInteger) value).toString(radix);
+ }
+ else {
+ strValue = Integer.toString((Integer) value, radix);
+ }
+
+ if (spec.alternate) {
+ if (radix == 2)
+ strValue = "0b" + strValue;
+ else if (radix == 8)
+ strValue = "0o" + strValue;
+ else if (radix == 16)
+ strValue = "0x" + strValue;
+ }
+ if (spec.type == 'X') {
+ strValue = strValue.toUpperCase();
+ }
+
+ if (sign >= 0) {
+ if (spec.sign == '+') {
+ strValue = "+" + strValue;
+ } else if (spec.sign == ' ') {
+ strValue = " " + strValue;
+ }
+ }
+ }
+ if (spec.align == '=' && (sign < 0 || spec.sign == '+' || spec.sign == ' ')) {
+ char signChar = strValue.charAt(0);
+ return signChar + spec.pad(strValue.substring(1), '>', 1);
+ }
+ return spec.pad(strValue, '>', 0);
+ }
+
+ @Override
public boolean isIndex() {
return true;
}
Modified: trunk/jython/src/org/python/core/PyLong.java
===================================================================
--- trunk/jython/src/org/python/core/PyLong.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/PyLong.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -982,6 +982,16 @@
}
@Override
+ public PyObject __format__(PyObject format_spec) {
+ return long___format__(format_spec);
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.long___format___doc)
+ final PyObject long___format__(PyObject format_spec) {
+ return PyInteger.formatImpl(getValue(), format_spec);
+ }
+
+ @Override
public boolean isIndex() {
return true;
}
Modified: trunk/jython/src/org/python/core/PyObject.java
===================================================================
--- trunk/jython/src/org/python/core/PyObject.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/PyObject.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -1710,6 +1710,16 @@
return false;
}
+ public PyObject __format__(PyObject format_spec) {
+ return object___format__(format_spec);
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.object___format___doc)
+ final PyObject object___format__(PyObject format_spec) {
+ PyString str = __str__();
+ return str.__format__(format_spec);
+ }
+
/**
* Implements boolean not
*
Modified: trunk/jython/src/org/python/core/PyString.java
===================================================================
--- trunk/jython/src/org/python/core/PyString.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/PyString.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -3,6 +3,10 @@
import java.math.BigInteger;
+import org.python.core.stringlib.FieldNameIterator;
+import org.python.core.stringlib.InternalFormatSpec;
+import org.python.core.stringlib.InternalFormatSpecParser;
+import org.python.core.stringlib.MarkupIterator;
import org.python.core.util.ExtraMath;
import org.python.core.util.StringUtil;
import org.python.expose.ExposedMethod;
@@ -2510,6 +2514,155 @@
return codecs.decode(this, encoding, errors);
}
+ @ExposedMethod(doc = BuiltinDocs.str__formatter_parser_doc)
+ final PyObject str__formatter_parser() {
+ return new MarkupIterator(getString());
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.str__formatter_field_name_split_doc)
+ final PyObject str__formatter_field_name_split() {
+ FieldNameIterator iterator = new FieldNameIterator(getString());
+ Object headObj = iterator.head();
+ PyObject head = headObj instanceof Integer
+ ? new PyInteger((Integer) headObj)
+ : new PyString((String) headObj);
+ return new PyTuple(head, iterator);
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.str_format_doc)
+ final PyObject str_format(PyObject[] args, String[] keywords) {
+ try {
+ return new PyString(buildFormattedString(getString(), args, keywords));
+ } catch(IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ }
+
+ private String buildFormattedString(String value, PyObject[] args, String[] keywords) {
+ StringBuilder result = new StringBuilder();
+ MarkupIterator it = new MarkupIterator(value);
+ while (true) {
+ MarkupIterator.Chunk chunk = it.nextChunk();
+ if (chunk == null) {
+ break;
+ }
+ result.append(chunk.literalText);
+ if (chunk.fieldName.length() > 0) {
+ outputMarkup(result, chunk, args, keywords);
+ }
+ }
+ return result.toString();
+ }
+
+ private void outputMarkup(StringBuilder result, MarkupIterator.Chunk chunk,
+ PyObject[] args, String[] keywords) {
+ PyObject fieldObj = getFieldObject(chunk.fieldName, args, keywords);
+ if (fieldObj == null) {
+ return;
+ }
+ if ("r".equals(chunk.conversion)) {
+ fieldObj = fieldObj.__repr__();
+ }
+ else if ("s".equals(chunk.conversion)) {
+ fieldObj = fieldObj.__str__();
+ }
+ else if (chunk.conversion != null) {
+ throw Py.ValueError("Unknown conversion specifier " + chunk.conversion);
+ }
+ String formatSpec = chunk.formatSpec;
+ if (chunk.formatSpecNeedsExpanding) {
+ formatSpec = buildFormattedString(formatSpec, args, keywords);
+ }
+ renderField(fieldObj, formatSpec, result);
+ }
+
+ private PyObject getFieldObject(String fieldName, PyObject[] args, String[] keywords) {
+ FieldNameIterator iterator = new FieldNameIterator(fieldName);
+ Object head = iterator.head();
+ PyObject obj = null;
+ int positionalCount = args.length - keywords.length;
+ if (head instanceof Integer) {
+ int index = (Integer) head;
+ if (index >= positionalCount) {
+ throw Py.IndexError("tuple index out of range");
+ }
+ obj = args[index];
+ }
+ else {
+ for (int i = 0; i < keywords.length; i++) {
+ if (keywords[i].equals(head)) {
+ obj = args[positionalCount+i];
+ break;
+ }
+ }
+ if (obj == null) {
+ throw Py.KeyError((String) head);
+ }
+ }
+ if (obj != null) {
+ while (true) {
+ FieldNameIterator.Chunk chunk = iterator.nextChunk();
+ if (chunk == null) {
+ break;
+ }
+ if (chunk.is_attr) {
+ obj = obj.__getattr__((String) chunk.value);
+ }
+ else {
+ PyObject key = chunk.value instanceof String
+ ? new PyString((String) chunk.value)
+ : new PyInteger((Integer) chunk.value);
+ obj = obj.__getitem__(key);
+ }
+ if (obj == null) break;
+ }
+ }
+ return obj;
+ }
+
+ private void renderField(PyObject fieldObj, String formatSpec, StringBuilder result) {
+ PyString formatSpecStr = formatSpec == null ? Py.EmptyString : new PyString(formatSpec);
+ result.append(fieldObj.__format__(formatSpecStr).asString());
+ }
+
+ @Override
+ public PyObject __format__(PyObject format_spec) {
+ return str___format__(format_spec);
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.str___format___doc)
+ final PyObject str___format__(PyObject format_spec) {
+ if (format_spec instanceof PyString) {
+ String result;
+ try {
+ String specString = ((PyString) format_spec).getString();
+ InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
+ result = formatString(getString(), spec);
+ } catch (IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ if (format_spec instanceof PyUnicode) {
+ return new PyUnicode(result);
+ }
+ return new PyString(result);
+ }
+ throw Py.TypeError("__format__ requires str or unicode");
+ }
+
+ /**
+ * Internal implementation of str.__format__()
+ *
+ * @param text the text to format
+ * @param spec the PEP 3101 formatting specification
+ * @return the result of the formatting
+ */
+ public static String formatString(String text, InternalFormatSpec spec) {
+ if (spec.precision >= 0 && text.length() > spec.precision) {
+ text = text.substring(0, spec.precision);
+ }
+ return spec.pad(text, '<', 0);
+ }
+
/* arguments' conversion helper */
@Override
Modified: trunk/jython/src/org/python/core/__builtin__.java
===================================================================
--- trunk/jython/src/org/python/core/__builtin__.java 2011-03-21 05:46:52 UTC (rev 7256)
+++ trunk/jython/src/org/python/core/__builtin__.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -358,6 +358,7 @@
dict.__setitem__("sorted", new SortedFunction());
dict.__setitem__("all", new AllFunction());
dict.__setitem__("any", new AnyFunction());
+ dict.__setitem__("format", new FormatFunction());
}
public static PyObject abs(PyObject o) {
@@ -1303,6 +1304,25 @@
}
}
+class FormatFunction extends PyBuiltinFunctionNarrow {
+ FormatFunction() {
+ super("format", 1, 2,
+ "format(value[, format_spec]) -> string\n\n" +
+ "Returns value.__format__(format_spec)\n" +
+ "format_spec defaults to \"\"");
+ }
+
+ @Override
+ public PyObject __call__(PyObject arg1) {
+ return __call__(arg1, new PyString(""));
+ }
+
+ @Override
+ public PyObject __call__(PyObject arg1, PyObject arg2) {
+ return arg1.__format__(arg2);
+ }
+}
+
class MaxFunction extends PyBuiltinFunction {
MaxFunction() {
super("max",
Added: trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java (rev 0)
+++ trunk/jython/src/org/python/core/stringlib/FieldNameIterator.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -0,0 +1,117 @@
+package org.python.core.stringlib;
+
+import org.python.core.*;
+import org.python.expose.ExposedMethod;
+import org.python.expose.ExposedType;
+
+/**
+ * Provides an implementation of str._formatter_field_name_split()
+ */
+@ExposedType(name = "fieldnameiterator", base = PyObject.class, isBaseType = false)
+public class FieldNameIterator extends PyObject {
+ private String markup;
+ private Object head;
+ private int index;
+
+ public FieldNameIterator(String markup) {
+ this.markup = markup;
+ this.index = nextDotOrBracket(markup);
+ String headStr = markup.substring(0, index);
+ try {
+ this.head = Integer.parseInt(headStr);
+ } catch (NumberFormatException e) {
+ this.head = headStr;
+ }
+ }
+
+ @Override
+ public PyObject __iter__() {
+ return this;
+ }
+
+ @ExposedMethod
+ public PyObject fieldnameiterator___iter__() {
+ return this;
+ }
+
+ public PyObject __iternext__() {
+ Chunk chunk = nextChunk();
+ if (chunk == null) {
+ return null;
+ }
+ PyObject[] elements = new PyObject[2];
+ elements [0] = new PyBoolean(chunk.is_attr);
+ if (chunk.value instanceof Integer) {
+ elements [1] = new PyInteger((Integer) chunk.value);
+ }
+ else {
+ elements [1] = new PyString((String) chunk.value);
+ }
+ return new PyTuple(elements);
+ }
+
+ @ExposedMethod
+ public PyObject fieldnameiterator___iternext__() {
+ return __iternext__();
+ }
+
+ private int nextDotOrBracket(String markup) {
+ int dotPos = markup.indexOf('.', index);
+ if (dotPos < 0) dotPos = markup.length();
+ int bracketPos = markup.indexOf('[', index);
+ if (bracketPos < 0) bracketPos = markup.length();
+ return Math.min(dotPos, bracketPos);
+ }
+
+ public Object head() {
+ return head;
+ }
+
+ public Chunk nextChunk() {
+ if (index == markup.length()) {
+ return null;
+ }
+ Chunk chunk = new Chunk();
+ if (markup.charAt(index) == '[') {
+ parseItemChunk(chunk);
+ }
+ else if (markup.charAt(index) == '.') {
+ parseAttrChunk(chunk);
+ }
+ return chunk;
+ }
+
+ private void parseItemChunk(Chunk chunk) {
+ chunk.is_attr = false;
+ int endBracket = markup.indexOf(']', index+1);
+ if (endBracket < 0) {
+ throw new IllegalArgumentException("Missing ']' in format string");
+ }
+ String itemValue = markup.substring(index+1, endBracket);
+ if (itemValue.length() == 0) {
+ throw new IllegalArgumentException("Empty attribute in format string");
+ }
+ try {
+ chunk.value = Integer.parseInt(itemValue);
+ } catch (NumberFormatException e) {
+ chunk.value = itemValue;
+ }
+ index = endBracket+1;
+ }
+
+ private void parseAttrChunk(Chunk chunk) {
+ index++; // skip dot
+ chunk.is_attr = true;
+ int pos = nextDotOrBracket(markup);
+ if (pos == index) {
+ throw new IllegalArgumentException("Empty attribute in format string");
+ }
+ chunk.value = markup.substring(index, pos);
+ index = pos;
+ }
+
+ public static class Chunk {
+ public boolean is_attr;
+ public Object value; // Integer or String
+ }
+}
Added: trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java (rev 0)
+++ trunk/jython/src/org/python/core/stringlib/InternalFormatSpec.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -0,0 +1,42 @@
+package org.python.core.stringlib;
+
+/**
+ * Parsed PEP-3101 format specification of a single field.
+ */
+public final class InternalFormatSpec {
+ public char fill_char;
+ public char align;
+ public boolean alternate;
+ public char sign;
+ public int width = -1;
+ public int precision = -1;
+ public char type;
+
+ public String pad(String value, char defaultAlign, int leaveWidth) {
+ int remaining = width - value.length() - leaveWidth;
+ if (remaining <= 0) {
+ return value;
+ }
+ StringBuilder result = new StringBuilder();
+ int leading = remaining;
+ int useAlign = align;
+ if (useAlign == 0) {
+ useAlign = defaultAlign;
+ }
+ if (useAlign == '^') {
+ leading = remaining/2;
+ }
+ else if (useAlign == '<') {
+ leading = 0;
+ }
+ char fill = fill_char != 0 ? fill_char : ' ';
+ for (int i = 0; i < leading; i++) {
+ result.append(fill);
+ }
+ result.append(value);
+ for (int i = 0; i < remaining-leading; i++) {
+ result.append(fill);
+ }
+ return result.toString();
+ }
+}
Added: trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java (rev 0)
+++ trunk/jython/src/org/python/core/stringlib/InternalFormatSpecParser.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -0,0 +1,83 @@
+package org.python.core.stringlib;
+
+/**
+ * Parser for PEP-3101 field format specifications.
+ */
+public class InternalFormatSpecParser {
+ private String spec;
+ private int index;
+
+ public InternalFormatSpecParser(String spec) {
+ this.spec = spec;
+ this.index = 0;
+ }
+
+ private static boolean isAlign(char c) {
+ switch(c) {
+ case '<':
+ case '>':
+ case '=':
+ case '^':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public InternalFormatSpec parse() {
+ InternalFormatSpec result = new InternalFormatSpec();
+ if (spec.length() >= 1 && isAlign(spec.charAt(0))) {
+ result.align = spec.charAt(index);
+ index++;
+ }
+ else if (spec.length() >= 2 && isAlign(spec.charAt(1))) {
+ result.fill_char = spec.charAt(0);
+ result.align = spec.charAt(1);
+ index += 2;
+ }
+ if (isAt("+- ")) {
+ result.sign = spec.charAt(index);
+ index++;
+ }
+ if (isAt("#")) {
+ result.alternate = true;
+ index++;
+ }
+ if (isAt("0")) {
+ result.align = '=';
+ result.fill_char = '0';
+ index++;
+ }
+ result.width = getInteger();
+ if (isAt(".")) {
+ index++;
+ result.precision = getInteger();
+ if (result.precision == -1) {
+ throw new IllegalArgumentException("Format specifier missing precision");
+ }
+ }
+ if (index < spec.length()) {
+ result.type = spec.charAt(index);
+ if (index + 1 != spec.length()) {
+ throw new IllegalArgumentException("Invalid conversion specification");
+ }
+ }
+ return result;
+ }
+
+ private int getInteger() {
+ int value = 0;
+ boolean empty = true;
+ while (index < spec.length() && spec.charAt(index) >= '0' && spec.charAt(index) <= '9') {
+ value = value * 10 + spec.charAt(index) - '0';
+ index++;
+ empty = false;
+ }
+ if (empty) return -1;
+ return value;
+ }
+
+ private boolean isAt(String chars) {
+ return index < spec.length() && chars.indexOf(spec.charAt(index)) >= 0;
+ }
+}
Added: trunk/jython/src/org/python/core/stringlib/MarkupIterator.java
===================================================================
--- trunk/jython/src/org/python/core/stringlib/MarkupIterator.java (rev 0)
+++ trunk/jython/src/org/python/core/stringlib/MarkupIterator.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -0,0 +1,159 @@
+package org.python.core.stringlib;
+
+import org.python.core.*;
+import org.python.expose.ExposedMethod;
+import org.python.expose.ExposedType;
+
+/**
+ * Provides an implementation of str._formatter_parser()
+ */
+@ExposedType(name = "formatteriterator", base = PyObject.class, isBaseType = false)
+public class MarkupIterator extends PyObject {
+ private final String markup;
+ private int index;
+
+ public MarkupIterator(String markup) {
+ this.markup = markup;
+ }
+
+ @Override
+ public PyObject __iter__() {
+ return this;
+ }
+
+ @ExposedMethod
+ public PyObject formatteriterator___iter__() {
+ return this;
+ }
+
+ public PyObject __iternext__() {
+ Chunk chunk;
+ try {
+ chunk = nextChunk();
+ } catch (IllegalArgumentException e) {
+ throw Py.ValueError(e.getMessage());
+ }
+ if (chunk == null) {
+ return null;
+ }
+ PyObject[] elements = new PyObject[4];
+ elements[0] = new PyString(chunk.literalText);
+ elements[1] = new PyString(chunk.fieldName);
+ if (chunk.fieldName.length() > 0) {
+ elements[2] = chunk.formatSpec == null ? Py.EmptyString : new PyString(chunk.formatSpec);
+ }
+ else {
+ elements[2] = Py.None;
+ }
+ elements[3] = chunk.conversion == null ? Py.None : new PyString(chunk.conversion);
+ return new PyTuple(elements);
+ }
+
+ @ExposedMethod
+ public PyObject formatteriterator___iternext__() {
+ return __iternext__();
+ }
+
+ public Chunk nextChunk() {
+ if (index == markup.length()) {
+ return null;
+ }
+ Chunk result = new Chunk();
+ int pos = index;
+ while(true) {
+ pos = indexOfFirst(markup, pos, '{', '}');
+ if (pos >= 0 && pos < markup.length()-1 &&
+ markup.charAt(pos+1) == markup.charAt(pos)) {
+ pos += 2; // skip escaped bracket
+ }
+ else if (pos >= 0 && markup.charAt(pos) == '}') {
+ throw new IllegalArgumentException("Single '}' encountered in format string");
+ }
+ else {
+ break;
+ }
+ }
+ if (pos < 0) {
+ result.literalText = unescapeBraces(markup.substring(index));
+ result.fieldName = "";
+ index = markup.length();
+ }
+ else {
+ result.literalText = unescapeBraces(markup.substring(index, pos));
+ pos++;
+ int fieldStart = pos;
+ int count = 1;
+ while (pos < markup.length()) {
+ if (markup.charAt(pos) == '{') {
+ count++;
+ result.formatSpecNeedsExpanding = true;
+ }
+ else if (markup.charAt(pos) == '}') {
+ count--;
+ if (count == 0) {
+ parseField(result, markup.substring(fieldStart, pos));
+ pos++;
+ break;
+ }
+ }
+ pos++;
+ }
+ if (count > 0)
+ throw new IllegalArgumentException("Single '{' encountered in format string");
+ index = pos;
+ }
+ return result;
+ }
+
+ private String unescapeBraces(String substring) {
+ return substring.replace("{{", "{").replace("}}", "}");
+ }
+
+ private void parseField(Chunk result, String fieldMarkup) {
+ int pos = indexOfFirst(fieldMarkup, 0, '!', ':');
+ if (pos >= 0) {
+ result.fieldName = fieldMarkup.substring(0, pos);
+ if (fieldMarkup.charAt(pos) == '!') {
+ if (pos == fieldMarkup.length() - 1) {
+ throw new IllegalArgumentException("end of format while " +
+ "looking for conversion specifier");
+ }
+ result.conversion = fieldMarkup.substring(pos + 1, pos + 2);
+ pos += 2;
+ if (pos < fieldMarkup.length()) {
+ if (fieldMarkup.charAt(pos) != ':') {
+ throw new IllegalArgumentException("expected ':' " +
+ "after conversion specifier");
+ }
+ result.formatSpec = fieldMarkup.substring(pos+1);
+ }
+ }
+ else {
+ result.formatSpec = fieldMarkup.substring(pos+1);
+ }
+ }
+ else {
+ result.fieldName = fieldMarkup;
+ }
+ }
+
+ private int indexOfFirst(String s, int start, char c1, char c2) {
+ int i1 = s.indexOf(c1, start);
+ int i2 = s.indexOf(c2, start);
+ if (i1 == -1) {
+ return i2;
+ }
+ if (i2 == -1) {
+ return i1;
+ }
+ return Math.min(i1, i2);
+ }
+
+ public static final class Chunk {
+ public String literalText;
+ public String fieldName;
+ public String formatSpec;
+ public String conversion;
+ public boolean formatSpecNeedsExpanding;
+ }
+}
Added: trunk/jython/tests/java/org/python/core/StringFormatTest.java
===================================================================
--- trunk/jython/tests/java/org/python/core/StringFormatTest.java (rev 0)
+++ trunk/jython/tests/java/org/python/core/StringFormatTest.java 2011-03-21 05:57:39 UTC (rev 7257)
@@ -0,0 +1,216 @@
+package org.python.core;
+
+import junit.framework.TestCase;
+import org.python.core.stringlib.FieldNameIterator;
+import org.python.core.stringlib.InternalFormatSpec;
+import org.python.core.stringlib.InternalFormatSpecParser;
+import org.python.core.stringlib.MarkupIterator;
+
+/**
+ * Tests for internal bits and pieces of string.format implementation.
+ */
+public class StringFormatTest extends TestCase {
+ public void testInternalFormatSpec() {
+ InternalFormatSpec spec = new InternalFormatSpecParser("x").parse();
+ assertEquals('x', spec.type);
+
+ spec = new InternalFormatSpecParser("<x").parse();
+ assertEquals('<', spec.align);
+ assertEquals('x', spec.type);
+
+ spec = new InternalFormatSpecParser("~<x").parse();
+ assertEquals('~', spec.fill_char);
+ assertEquals('<', spec.align);
+ assertEquals('x', spec.type);
+
+ spec = new InternalFormatSpecParser("+x").parse();
+ assertEquals('+', spec.sign);
+ assertEquals('x', spec.type);
+
+ spec = new InternalFormatSpecParser("#x").parse();
+ assertEquals(true, spec.alternate);
+
+ spec = new InternalFormatSpecParser("0x").parse();
+ assertEquals('=', spec.align);
+ assertEquals('0', spec.fill_char);
+
+ spec = new InternalFormatSpecParser("123x").parse();
+ assertEquals(123, spec.width);
+
+ spec = new InternalFormatSpecParser("123.456x").parse();
+ assertEquals(123, spec.width);
+ assertEquals(456, spec.precision);
+
+ assertParseError("123.x", "Format specifier missing precision");
+
+ assertParseError("123xx", "Invalid conversion specification");
+
+ spec = new InternalFormatSpecParser("").parse();
+ assertEquals(0, spec.type);
+ }
+
+ private void assertParseError(String spec, String expected) {
+ String error = null;
+ try {
+ new InternalFormatSpecParser(spec).parse();
+ } catch (IllegalArgumentException e) {
+ error = e.getMessage();
+ }
+ assertEquals(expected, error);
+ }
+
+ public void testFormatIntOrLong() {
+ InternalFormatSpec spec = new InternalFormatSpec();
+ spec.type = 'd';
+ assertEquals("123", PyInteger.formatIntOrLong(123, spec));
+ spec.type = 'o';
+ assertEquals("173", PyInteger.formatIntOrLong(123, spec));
+ spec.type = 'x';
+ assertEquals("7b", PyInteger.formatIntOrLong(123, spec));
+ spec.type = 'X';
+ assertEquals("7B", PyInteger.formatIntOrLong(123, spec));
+ spec.type = 'b';
+ assertEquals("1111011", PyInteger.formatIntOrLong(123, spec));
+
+ spec.alternate = true;
+ spec.type = 'o';
+ assertEquals("0o173", PyInteger.formatIntOrLong(123, spec));
+ spec.type = 'X';
+ assertEquals("0X7B", PyInteger.formatIntOrLong(123, spec));
+ spec.alternate = false;
+
+ spec.type = 'c';
+ assertEquals("{", PyInteger.formatIntOrLong(123, spec));
+
+ spec.type = 'd';
+ spec.sign = '+';
+ assertEquals("+123", PyInteger.formatIntOrLong(123, spec));
+ spec.sign = ' ';
+ assertEquals(" 123", PyInteger.formatIntOrLong(123, spec));
+
+ spec.sign = 0;
+ spec.width = 5;
+ assertEquals(" 123", PyInteger.formatIntOrLong(123, spec));
+
+ spec.align = '^';
+ spec.width = 6;
+ assertEquals(" 123 ", PyInteger.formatIntOrLong(123, spec));
+
+ spec.align = '<';
+ spec.width = 5;
+ spec.fill_char = '~';
+ assertEquals("123~~", PyInteger.formatIntOrLong(123, spec));
+
+ spec.align = '=';
+ spec.width = 6;
+ spec.fill_char = '0';
+ spec.sign = '+';
+ assertEquals("+00123", PyInteger.formatIntOrLong(123, spec));
+
+ spec.precision = 1;
+ assertFormatError(123, spec, "Precision not allowed in integer format specifier");
+
+ spec.precision = -1;
+ spec.sign = '+';
+ spec.type = 'c';
+ assertFormatError(123, spec, "Sign not allowed with integer format specifier 'c'");
+
+ spec.sign = 0;
+ assertFormatError(0x11111, spec, "%c arg not in range(0x10000)");
+ }
+
+ public void testFormatString() {
+ InternalFormatSpec spec = new InternalFormatSpec();
+ assertEquals("abc", PyString.formatString("abc", spec));
+
+ spec.precision = 3;
+ assertEquals("abc", PyString.formatString("abcdef", spec));
+
+ spec.precision = -1;
+ spec.width = 6;
+ assertEquals("abc ", PyString.formatString("abc", spec));
+ }
+
+ private void assertFormatError(int value, InternalFormatSpec spec, String expected) {
+ String error = null;
+ try {
+ PyInteger.formatIntOrLong(value, spec);
+ } catch (IllegalArgumentException e) {
+ error = e.getMessage();
+ }
+ assertEquals(expected, error);
+ }
+
+ public void testMarkupIterator() {
+ MarkupIterator iterator = new MarkupIterator("abc");
+ assertEquals("abc", iterator.nextChunk().literalText);
+ assertNull(iterator.nextChunk());
+
+ iterator = new MarkupIterator("First, thou shalt count to {0}");
+ MarkupIterator.Chunk chunk = iterator.nextChunk();
+ assertEquals("First, thou shalt count to ", chunk.literalText);
+ assertEquals("0", chunk.fieldName);
+ assertNull(iterator.nextChunk());
+
+ iterator = new MarkupIterator("Weight in tons {0.weight!r:s}");
+ chunk = iterator.nextChunk();
+ assertEquals("Weight in tons ", chunk.literalText);
+ assertEquals("0.weight", chunk.fieldName);
+ assertEquals("r", chunk.conversion);
+ assertEquals("s", chunk.formatSpec);
+
+ chunk = new MarkupIterator("{{").nextChunk();
+ assertEquals("{", chunk.literalText);
+
+ chunk = new MarkupIterator("}}").nextChunk();
+ assertEquals("}", chunk.literalText);
+
+ chunk = new MarkupIterator("{{}}").nextChunk();
+ assertEquals("{}", chunk.literalText);
+
+ chunk = new MarkupIterator("{0:.{1}}").nextChunk();
+ assertEquals("0", chunk.fieldName);
+ assertEquals(".{1}", chunk.formatSpec);
+ assertTrue(chunk.formatSpecNeedsExpanding);
+
+ assertMarkupError("{!}", "end of format while looking for conversion specifier");
+ assertMarkupError("{!rrrr}", "expected ':' after conversion specifier");
+ assertMarkupError("{", "Single '{' encountered in format string");
+ assertMarkupError("}", "Single '}' encountered in format string");
+ }
+
+ private void assertMarkupError(String markup, String expected) {
+ MarkupIterator iterator = new MarkupIterator(markup);
+ String error = null;
+ try {
+ iterator.nextChunk();
+ } catch (IllegalArgumentException e) {
+ error = e.getMessage();
+ }
+ assertEquals(expected, error);
+ }
+
+ public void testFieldNameIterator() {
+ FieldNameIterator it = new FieldNameIterator("abc");
+ assertEquals("abc", it.head());
+ assertNull(it.nextChunk());
+
+ it = new FieldNameIterator("3");
+ assertEquals(3, it.head());
+ assertNull(it.nextChunk());
+
+ it = new FieldNameIterator("abc[0]");
+ assertEquals("abc", it.head());
+ FieldNameIterator.Chunk chunk = it.nextChunk();
+ assertEquals(0, chunk.value);
+ assertFalse(chunk.is_attr);
+ assertNull(it.nextChunk());
+
+ it = new FieldNameIterator("abc.def");
+ assertEquals("abc", it.head());
+ chunk = it.nextChunk();
+ assertEquals("def", chunk.value);
+ assertTrue(chunk.is_attr);
+ assertNull(it.nextChunk());
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 05:46:58
|
Revision: 7256
http://jython.svn.sourceforge.net/jython/?rev=7256&view=rev
Author: pjenvey
Date: 2011-03-21 05:46:52 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
update test_str to 2.6
Modified Paths:
--------------
trunk/jython/Lib/test/test_str.py
Modified: trunk/jython/Lib/test/test_str.py
===================================================================
--- trunk/jython/Lib/test/test_str.py 2011-03-21 05:36:00 UTC (rev 7255)
+++ trunk/jython/Lib/test/test_str.py 2011-03-21 05:46:52 UTC (rev 7256)
@@ -1,5 +1,4 @@
-import unittest
import struct
import sys
from test import test_support, string_tests
@@ -18,6 +17,20 @@
def fixtype(self, obj):
return obj
+ def test_basic_creation(self):
+ self.assertEqual(str(''), '')
+ self.assertEqual(str(0), '0')
+ self.assertEqual(str(0L), '0')
+ self.assertEqual(str(()), '()')
+ self.assertEqual(str([]), '[]')
+ self.assertEqual(str({}), '{}')
+ a = []
+ a.append(a)
+ self.assertEqual(str(a), '[[...]]')
+ a = {}
+ a[0] = a
+ self.assertEqual(str(a), '{0: {...}}')
+
def test_formatting(self):
string_tests.MixinStrUnicodeUserStringTest.test_formatting(self)
self.assertRaises(OverflowError, '%c'.__mod__, 0x1234)
@@ -96,7 +109,272 @@
return
self.assertRaises(OverflowError, 't\tt\t'.expandtabs, sys.maxint)
+ def test__format__(self):
+ def test(value, format, expected):
+ # test both with and without the trailing 's'
+ self.assertEqual(value.__format__(format), expected)
+ self.assertEqual(value.__format__(format + 's'), expected)
+ test('', '', '')
+ test('abc', '', 'abc')
+ test('abc', '.3', 'abc')
+ test('ab', '.3', 'ab')
+ test('abcdef', '.3', 'abc')
+ test('abcdef', '.0', '')
+ test('abc', '3.3', 'abc')
+ test('abc', '2.3', 'abc')
+ test('abc', '2.2', 'ab')
+ test('abc', '3.2', 'ab ')
+ test('result', 'x<0', 'result')
+ test('result', 'x<5', 'result')
+ test('result', 'x<6', 'result')
+ test('result', 'x<7', 'resultx')
+ test('result', 'x<8', 'resultxx')
+ test('result', ' <7', 'result ')
+ test('result', '<7', 'result ')
+ test('result', '>7', ' result')
+ test('result', '>8', ' result')
+ test('result', '^8', ' result ')
+ test('result', '^9', ' result ')
+ test('result', '^10', ' result ')
+ test('a', '10000', 'a' + ' ' * 9999)
+ test('', '10000', ' ' * 10000)
+ test('', '10000000', ' ' * 10000000)
+
+ def test_format(self):
+ self.assertEqual(''.format(), '')
+ self.assertEqual('a'.format(), 'a')
+ self.assertEqual('ab'.format(), 'ab')
+ self.assertEqual('a{{'.format(), 'a{')
+ self.assertEqual('a}}'.format(), 'a}')
+ self.assertEqual('{{b'.format(), '{b')
+ self.assertEqual('}}b'.format(), '}b')
+ self.assertEqual('a{{b'.format(), 'a{b')
+
+ # examples from the PEP:
+ import datetime
+ self.assertEqual("My name is {0}".format('Fred'), "My name is Fred")
+ self.assertEqual("My name is {0[name]}".format(dict(name='Fred')),
+ "My name is Fred")
+ self.assertEqual("My name is {0} :-{{}}".format('Fred'),
+ "My name is Fred :-{}")
+
+ d = datetime.date(2007, 8, 18)
+ self.assertEqual("The year is {0.year}".format(d),
+ "The year is 2007")
+
+ # classes we'll use for testing
+ class C:
+ def __init__(self, x=100):
+ self._x = x
+ def __format__(self, spec):
+ return spec
+
+ class D:
+ def __init__(self, x):
+ self.x = x
+ def __format__(self, spec):
+ return str(self.x)
+
+ # class with __str__, but no __format__
+ class E:
+ def __init__(self, x):
+ self.x = x
+ def __str__(self):
+ return 'E(' + self.x + ')'
+
+ # class with __repr__, but no __format__ or __str__
+ class F:
+ def __init__(self, x):
+ self.x = x
+ def __repr__(self):
+ return 'F(' + self.x + ')'
+
+ # class with __format__ that forwards to string, for some format_spec's
+ class G:
+ def __init__(self, x):
+ self.x = x
+ def __str__(self):
+ return "string is " + self.x
+ def __format__(self, format_spec):
+ if format_spec == 'd':
+ return 'G(' + self.x + ')'
+ return object.__format__(self, format_spec)
+
+ # class that returns a bad type from __format__
+ class H:
+ def __format__(self, format_spec):
+ return 1.0
+
+ class I(datetime.date):
+ def __format__(self, format_spec):
+ return self.strftime(format_spec)
+
+ class J(int):
+ def __format__(self, format_spec):
+ return int.__format__(self * 2, format_spec)
+
+
+ self.assertEqual(''.format(), '')
+ self.assertEqual('abc'.format(), 'abc')
+ self.assertEqual('{0}'.format('abc'), 'abc')
+ self.assertEqual('{0:}'.format('abc'), 'abc')
+ self.assertEqual('X{0}'.format('abc'), 'Xabc')
+ self.assertEqual('{0}X'.format('abc'), 'abcX')
+ self.assertEqual('X{0}Y'.format('abc'), 'XabcY')
+ self.assertEqual('{1}'.format(1, 'abc'), 'abc')
+ self.assertEqual('X{1}'.format(1, 'abc'), 'Xabc')
+ self.assertEqual('{1}X'.format(1, 'abc'), 'abcX')
+ self.assertEqual('X{1}Y'.format(1, 'abc'), 'XabcY')
+ self.assertEqual('{0}'.format(-15), '-15')
+ self.assertEqual('{0}{1}'.format(-15, 'abc'), '-15abc')
+ self.assertEqual('{0}X{1}'.format(-15, 'abc'), '-15Xabc')
+ self.assertEqual('{{'.format(), '{')
+ self.assertEqual('}}'.format(), '}')
+ self.assertEqual('{{}}'.format(), '{}')
+ self.assertEqual('{{x}}'.format(), '{x}')
+ self.assertEqual('{{{0}}}'.format(123), '{123}')
+ self.assertEqual('{{{{0}}}}'.format(), '{{0}}')
+ self.assertEqual('}}{{'.format(), '}{')
+ self.assertEqual('}}x{{'.format(), '}x{')
+
+ # weird field names
+ self.assertEqual("{0[foo-bar]}".format({'foo-bar':'baz'}), 'baz')
+ self.assertEqual("{0[foo bar]}".format({'foo bar':'baz'}), 'baz')
+ self.assertEqual("{0[ ]}".format({' ':3}), '3')
+
+ self.assertEqual('{foo._x}'.format(foo=C(20)), '20')
+ self.assertEqual('{1}{0}'.format(D(10), D(20)), '2010')
+ self.assertEqual('{0._x.x}'.format(C(D('abc'))), 'abc')
+ self.assertEqual('{0[0]}'.format(['abc', 'def']), 'abc')
+ self.assertEqual('{0[1]}'.format(['abc', 'def']), 'def')
+ self.assertEqual('{0[1][0]}'.format(['abc', ['def']]), 'def')
+ self.assertEqual('{0[1][0].x}'.format(['abc', [D('def')]]), 'def')
+
+ # strings
+ self.assertEqual('{0:.3s}'.format('abc'), 'abc')
+ self.assertEqual('{0:.3s}'.format('ab'), 'ab')
+ self.assertEqual('{0:.3s}'.format('abcdef'), 'abc')
+ self.assertEqual('{0:.0s}'.format('abcdef'), '')
+ self.assertEqual('{0:3.3s}'.format('abc'), 'abc')
+ self.assertEqual('{0:2.3s}'.format('abc'), 'abc')
+ self.assertEqual('{0:2.2s}'.format('abc'), 'ab')
+ self.assertEqual('{0:3.2s}'.format('abc'), 'ab ')
+ self.assertEqual('{0:x<0s}'.format('result'), 'result')
+ self.assertEqual('{0:x<5s}'.format('result'), 'result')
+ self.assertEqual('{0:x<6s}'.format('result'), 'result')
+ self.assertEqual('{0:x<7s}'.format('result'), 'resultx')
+ self.assertEqual('{0:x<8s}'.format('result'), 'resultxx')
+ self.assertEqual('{0: <7s}'.format('result'), 'result ')
+ self.assertEqual('{0:<7s}'.format('result'), 'result ')
+ self.assertEqual('{0:>7s}'.format('result'), ' result')
+ self.assertEqual('{0:>8s}'.format('result'), ' result')
+ self.assertEqual('{0:^8s}'.format('result'), ' result ')
+ self.assertEqual('{0:^9s}'.format('result'), ' result ')
+ self.assertEqual('{0:^10s}'.format('result'), ' result ')
+ self.assertEqual('{0:10000}'.format('a'), 'a' + ' ' * 9999)
+ self.assertEqual('{0:10000}'.format(''), ' ' * 10000)
+ self.assertEqual('{0:10000000}'.format(''), ' ' * 10000000)
+
+ # format specifiers for user defined type
+ self.assertEqual('{0:abc}'.format(C()), 'abc')
+
+ # !r and !s coersions
+ self.assertEqual('{0!s}'.format('Hello'), 'Hello')
+ self.assertEqual('{0!s:}'.format('Hello'), 'Hello')
+ self.assertEqual('{0!s:15}'.format('Hello'), 'Hello ')
+ self.assertEqual('{0!s:15s}'.format('Hello'), 'Hello ')
+ self.assertEqual('{0!r}'.format('Hello'), "'Hello'")
+ self.assertEqual('{0!r:}'.format('Hello'), "'Hello'")
+ self.assertEqual('{0!r}'.format(F('Hello')), 'F(Hello)')
+
+ # test fallback to object.__format__
+ self.assertEqual('{0}'.format({}), '{}')
+ self.assertEqual('{0}'.format([]), '[]')
+ self.assertEqual('{0}'.format([1]), '[1]')
+ self.assertEqual('{0}'.format(E('data')), 'E(data)')
+ self.assertEqual('{0:^10}'.format(E('data')), ' E(data) ')
+ self.assertEqual('{0:^10s}'.format(E('data')), ' E(data) ')
+ self.assertEqual('{0:d}'.format(G('data')), 'G(data)')
+ self.assertEqual('{0:>15s}'.format(G('data')), ' string is data')
+ self.assertEqual('{0!s}'.format(G('data')), 'string is data')
+
+ self.assertEqual("{0:date: %Y-%m-%d}".format(I(year=2007,
+ month=8,
+ day=27)),
+ "date: 2007-08-27")
+
+ # test deriving from a builtin type and overriding __format__
+ self.assertEqual("{0}".format(J(10)), "20")
+
+
+ # string format specifiers
+ self.assertEqual('{0:}'.format('a'), 'a')
+
+ # computed format specifiers
+ self.assertEqual("{0:.{1}}".format('hello world', 5), 'hello')
+ self.assertEqual("{0:.{1}s}".format('hello world', 5), 'hello')
+ self.assertEqual("{0:.{precision}s}".format('hello world', precision=5), 'hello')
+ self.assertEqual("{0:{width}.{precision}s}".format('hello world', width=10, precision=5), 'hello ')
+ self.assertEqual("{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), 'hello ')
+
+ # test various errors
+ self.assertRaises(ValueError, '{'.format)
+ self.assertRaises(ValueError, '}'.format)
+ self.assertRaises(ValueError, 'a{'.format)
+ self.assertRaises(ValueError, 'a}'.format)
+ self.assertRaises(ValueError, '{a'.format)
+ self.assertRaises(ValueError, '}a'.format)
+ self.assertRaises(IndexError, '{0}'.format)
+ self.assertRaises(IndexError, '{1}'.format, 'abc')
+ self.assertRaises(KeyError, '{x}'.format)
+ self.assertRaises(ValueError, "}{".format)
+ self.assertRaises(ValueError, "{".format)
+ self.assertRaises(ValueError, "}".format)
+ self.assertRaises(ValueError, "abc{0:{}".format)
+ self.assertRaises(ValueError, "{0".format)
+ self.assertRaises(IndexError, "{0.}".format)
+ self.assertRaises(ValueError, "{0.}".format, 0)
+ self.assertRaises(IndexError, "{0[}".format)
+ self.assertRaises(ValueError, "{0[}".format, [])
+ self.assertRaises(KeyError, "{0]}".format)
+ self.assertRaises(ValueError, "{0.[]}".format, 0)
+ self.assertRaises(ValueError, "{0..foo}".format, 0)
+ self.assertRaises(ValueError, "{0[0}".format, 0)
+ self.assertRaises(ValueError, "{0[0:foo}".format, 0)
+ self.assertRaises(KeyError, "{c]}".format)
+ self.assertRaises(ValueError, "{{ {{{0}}".format, 0)
+ self.assertRaises(ValueError, "{0}}".format, 0)
+ self.assertRaises(KeyError, "{foo}".format, bar=3)
+ self.assertRaises(ValueError, "{0!x}".format, 3)
+ self.assertRaises(ValueError, "{0!}".format, 0)
+ self.assertRaises(ValueError, "{0!rs}".format, 0)
+ self.assertRaises(ValueError, "{!}".format)
+ self.assertRaises(ValueError, "{:}".format)
+ self.assertRaises(ValueError, "{:s}".format)
+ self.assertRaises(ValueError, "{}".format)
+
+ # issue 6089
+ self.assertRaises(ValueError, "{0[0]x}".format, [None])
+ self.assertRaises(ValueError, "{0[0](10)}".format, [None])
+
+ # can't have a replacement on the field name portion
+ self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4)
+
+ # exceed maximum recursion depth
+ self.assertRaises(ValueError, "{0:{1:{2}}}".format, 'abc', 's', '')
+ self.assertRaises(ValueError, "{0:{1:{2:{3:{4:{5:{6}}}}}}}".format,
+ 0, 1, 2, 3, 4, 5, 6, 7)
+
+ # string format spec errors
+ self.assertRaises(ValueError, "{0:-s}".format, '')
+ self.assertRaises(ValueError, format, "", "-")
+ self.assertRaises(ValueError, "{0:=s}".format, '')
+
+ def test_buffer_is_readonly(self):
+ self.assertRaises(TypeError, sys.stdin.readinto, b"")
+
+
def test_main():
test_support.run_unittest(StrTest)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 05:36:06
|
Revision: 7255
http://jython.svn.sourceforge.net/jython/?rev=7255&view=rev
Author: pjenvey
Date: 2011-03-21 05:36:00 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
update pkgutil to 2.6
Modified Paths:
--------------
trunk/jython/Lib/pkgutil.py
Modified: trunk/jython/Lib/pkgutil.py
===================================================================
--- trunk/jython/Lib/pkgutil.py 2011-03-21 05:01:00 UTC (rev 7254)
+++ trunk/jython/Lib/pkgutil.py 2011-03-21 05:36:00 UTC (rev 7255)
@@ -554,3 +554,40 @@
f.close()
return path
+
+def get_data(package, resource):
+ """Get a resource from a package.
+
+ This is a wrapper round the PEP 302 loader get_data API. The package
+ argument should be the name of a package, in standard module format
+ (foo.bar). The resource argument should be in the form of a relative
+ filename, using '/' as the path separator. The parent directory name '..'
+ is not allowed, and nor is a rooted name (starting with a '/').
+
+ The function returns a binary string, which is the contents of the
+ specified resource.
+
+ For packages located in the filesystem, which have already been imported,
+ this is the rough equivalent of
+
+ d = os.path.dirname(sys.modules[package].__file__)
+ data = open(os.path.join(d, resource), 'rb').read()
+
+ If the package cannot be located or loaded, or it uses a PEP 302 loader
+ which does not support get_data(), then None is returned.
+ """
+
+ loader = get_loader(package)
+ if loader is None or not hasattr(loader, 'get_data'):
+ return None
+ mod = sys.modules.get(package) or loader.load_module(package)
+ if mod is None or not hasattr(mod, '__file__'):
+ return None
+
+ # Modify the resource name to be compatible with the loader.get_data
+ # signature - an os.path format "filename" starting with the dirname of
+ # the package's __file__
+ parts = resource.split('/')
+ parts.insert(0, os.path.dirname(mod.__file__))
+ resource_name = os.path.join(*parts)
+ return loader.get_data(resource_name)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-21 05:01:07
|
Revision: 7254
http://jython.svn.sourceforge.net/jython/?rev=7254&view=rev
Author: pjenvey
Date: 2011-03-21 05:01:00 +0000 (Mon, 21 Mar 2011)
Log Message:
-----------
more 2.6 exception changes
Modified Paths:
--------------
trunk/jython/src/org/python/core/Py.java
trunk/jython/src/org/python/core/PyException.java
Removed Paths:
-------------
trunk/jython/Lib/test/exception_hierarchy.txt
Deleted: trunk/jython/Lib/test/exception_hierarchy.txt
===================================================================
--- trunk/jython/Lib/test/exception_hierarchy.txt 2011-03-20 19:56:03 UTC (rev 7253)
+++ trunk/jython/Lib/test/exception_hierarchy.txt 2011-03-21 05:01:00 UTC (rev 7254)
@@ -1,49 +0,0 @@
-BaseException
- +-- SystemExit
- +-- KeyboardInterrupt
- +-- GeneratorExit
- +-- Exception
- +-- StopIteration
- +-- StandardError
- | +-- ArithmeticError
- | | +-- FloatingPointError
- | | +-- OverflowError
- | | +-- ZeroDivisionError
- | +-- AssertionError
- | +-- AttributeError
- | +-- EnvironmentError
- | | +-- IOError
- | | +-- OSError
- | | +-- WindowsError (Windows)
- | | +-- VMSError (VMS)
- | +-- EOFError
- | +-- ImportError
- | +-- LookupError
- | | +-- IndexError
- | | +-- KeyError
- | +-- MemoryError
- | +-- NameError
- | | +-- UnboundLocalError
- | +-- ReferenceError
- | +-- RuntimeError
- | | +-- NotImplementedError
- | +-- SyntaxError
- | | +-- IndentationError
- | | +-- TabError
- | +-- SystemError
- | +-- TypeError
- | +-- ValueError
- | +-- UnicodeError
- | +-- UnicodeDecodeError
- | +-- UnicodeEncodeError
- | +-- UnicodeTranslateError
- +-- Warning
- +-- DeprecationWarning
- +-- PendingDeprecationWarning
- +-- RuntimeWarning
- +-- SyntaxWarning
- +-- UserWarning
- +-- FutureWarning
- +-- ImportWarning
- +-- UnicodeWarning
- +-- BytesWarning
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2011-03-20 19:56:03 UTC (rev 7253)
+++ trunk/jython/src/org/python/core/Py.java 2011-03-21 05:01:00 UTC (rev 7254)
@@ -353,6 +353,7 @@
public static PyException MemoryError(String message) {
return new PyException(Py.MemoryError, message);
}
+ public static PyObject BufferError;
public static PyObject ArithmeticError;
public static PyObject LookupError;
public static PyObject StandardError;
@@ -767,6 +768,7 @@
NameError = initExc("NameError", exc, dict);
UnboundLocalError = initExc("UnboundLocalError", exc, dict);
AttributeError = initExc("AttributeError", exc, dict);
+
SyntaxError = initExc("SyntaxError", exc, dict);
IndentationError = initExc("IndentationError", exc, dict);
TabError = initExc("TabError", exc, dict);
@@ -787,6 +789,7 @@
ReferenceError = initExc("ReferenceError", exc, dict);
SystemError = initExc("SystemError", exc, dict);
MemoryError = initExc("MemoryError", exc, dict);
+ BufferError = initExc("BufferError", exc, dict);
Warning = initExc("Warning", exc, dict);
UserWarning = initExc("UserWarning", exc, dict);
DeprecationWarning = initExc("DeprecationWarning", exc, dict);
Modified: trunk/jython/src/org/python/core/PyException.java
===================================================================
--- trunk/jython/src/org/python/core/PyException.java 2011-03-20 19:56:03 UTC (rev 7253)
+++ trunk/jython/src/org/python/core/PyException.java 2011-03-21 05:01:00 UTC (rev 7254)
@@ -237,6 +237,13 @@
return false;
}
+ if (exc instanceof PyString) {
+ Py.DeprecationWarning("catching of string exceptions is deprecated");
+ } else if (Options.py3kwarning && !isPy3kExceptionClass(exc)) {
+ Py.DeprecationWarning("catching classes that don't inherit from BaseException is not "
+ + "allowed in 3.x");
+ }
+
normalize();
// FIXME, see bug 737978
//
@@ -279,6 +286,16 @@
if (obj instanceof PyClass) {
return true;
}
+ return isPy3kExceptionClass(obj);
+ }
+
+ /**
+ * Determine whether obj is a Python 3 exception class
+ *
+ * @param obj a PyObject
+ * @return true if an exception
+ */
+ private static boolean isPy3kExceptionClass(PyObject obj) {
if (!(obj instanceof PyType)) {
return false;
}
@@ -286,7 +303,8 @@
if (type.isSubType(PyBaseException.TYPE)) {
return true;
}
- return type.getProxyType() != null && Throwable.class.isAssignableFrom(type.getProxyType());
+ return type.getProxyType() != null
+ && Throwable.class.isAssignableFrom(type.getProxyType());
}
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-20 19:56:10
|
Revision: 7253
http://jython.svn.sourceforge.net/jython/?rev=7253&view=rev
Author: pjenvey
Date: 2011-03-20 19:56:03 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
o 2.6 core exception related changes
o fix exceptions.getString allowing unicode
Modified Paths:
--------------
trunk/jython/Lib/test/junit_xml.py
trunk/jython/src/org/python/core/PyBaseException.java
trunk/jython/src/org/python/core/PyException.java
trunk/jython/src/org/python/core/exceptions.java
Modified: trunk/jython/Lib/test/junit_xml.py
===================================================================
--- trunk/jython/Lib/test/junit_xml.py 2011-03-20 19:43:03 UTC (rev 7252)
+++ trunk/jython/Lib/test/junit_xml.py 2011-03-20 19:56:03 UTC (rev 7253)
@@ -248,8 +248,8 @@
exc = exc_info[1]
if exc is None:
return safe_str(exc_info[0])
- if isinstance(exc, BaseException) and isinstance(exc.message, unicode):
- return safe_str(exc.message)
+ if isinstance(exc, BaseException) and isinstance(exc.args[0], unicode):
+ return safe_str(exc.args[0])
try:
return safe_str(str(exc))
except UnicodeEncodeError:
Modified: trunk/jython/src/org/python/core/PyBaseException.java
===================================================================
--- trunk/jython/src/org/python/core/PyBaseException.java 2011-03-20 19:43:03 UTC (rev 7252)
+++ trunk/jython/src/org/python/core/PyBaseException.java 2011-03-20 19:56:03 UTC (rev 7253)
@@ -18,9 +18,7 @@
public static final PyType TYPE = PyType.fromClass(PyBaseException.class);
/** Exception message. */
- @ExposedGet(doc = BuiltinDocs.BaseException_message_doc)
- @ExposedSet
- public PyObject message = Py.EmptyString;
+ private PyObject message = Py.EmptyString;
/** Exception's arguments. */
@ExposedGet(doc = BuiltinDocs.BaseException_args_doc)
@@ -52,25 +50,32 @@
}
}
+ @Override
public PyObject __getitem__(PyObject index) {
return BaseException___getitem__(index);
}
@ExposedMethod(doc = BuiltinDocs.BaseException___getitem___doc)
final PyObject BaseException___getitem__(PyObject index) {
+ Py.warnPy3k("__getitem__ not supported for exception classes in 3.x; use args "
+ + "attribute");
return args.__getitem__(index);
}
+ @Override
public PyObject __getslice__(PyObject start, PyObject stop) {
return BaseException___getslice__(start, stop);
}
@ExposedMethod(doc = BuiltinDocs.BaseException___getslice___doc)
final PyObject BaseException___getslice__(PyObject start, PyObject stop) {
+ Py.warnPy3k("__getslice__ not supported for exception classes in 3.x; use args "
+ + "attribute");
return args.__getslice__(start, stop);
}
+ @Override
public PyObject __reduce__() {
return BaseException___reduce__();
}
@@ -101,6 +106,7 @@
return Py.None;
}
+ @Override
public PyObject __findattr_ex__(String name) {
return BaseException___findattr__(name);
}
@@ -116,6 +122,7 @@
return super.__findattr_ex__(name);
}
+ @Override
public void __setattr__(String name, PyObject value) {
BaseException___setattr__(name, value);
}
@@ -126,16 +133,19 @@
super.__setattr__(name, value);
}
+ @Override
public PyObject fastGetDict() {
return __dict__;
}
+ @Override
@ExposedGet(name = "__dict__", doc = BuiltinDocs.BaseException___dict___doc)
public PyObject getDict() {
ensureDict();
return __dict__;
}
+ @Override
@ExposedSet(name = "__dict__")
public void setDict(PyObject val) {
if (!(val instanceof PyStringMap) && !(val instanceof PyDictionary)) {
@@ -145,12 +155,14 @@
}
private void ensureDict() {
+ // XXX: __dict__ should really be volatile
if (__dict__ == null) {
__dict__ = new PyStringMap();
}
}
- public PyString __str__() {
+ @Override
+ public PyString __str__() {
return BaseException___str__();
}
@@ -167,6 +179,35 @@
}
@Override
+ public PyUnicode __unicode__() {
+ return BaseException___unicode__();
+ }
+
+ @ExposedMethod(doc = BuiltinDocs.BaseException___unicode___doc)
+ final PyUnicode BaseException___unicode__() {
+ // CPython issue6108: if __str__ has been overridden in the subclass, unicode()
+ // should return the message returned by __str__ as used to happen before this
+ // method was implemented
+ PyType type = getType();
+ PyObject[] where = new PyObject[1];
+ PyObject str = type.lookup_where("__str__", where);
+ if (str != null && where[0] != TYPE) {
+ // Unlike str(), __str__ can return unicode (i.e. return the equivalent
+ // of unicode(e.__str__()) instead of unicode(str(e)))
+ return str.__get__(this, type).__call__().__unicode__();
+ }
+
+ switch (args.__len__()) {
+ case 0:
+ return new PyUnicode("");
+ case 1:
+ return args.__getitem__(0).__unicode__();
+ default:
+ return args.__unicode__();
+ }
+ }
+
+ @Override
public String toString() {
return BaseException_toString();
}
@@ -187,8 +228,33 @@
args = PyTuple.fromIterable(val);
}
+ @ExposedGet(name = "message", doc = BuiltinDocs.BaseException_message_doc)
+ public PyObject getMessage() {
+ PyObject message;
+
+ // if "message" is in self->dict, accessing a user-set message attribute
+ if (__dict__ != null && (message = __dict__.__finditem__("message")) != null) {
+ return message;
+ }
+
+ if (this.message == null) {
+ throw Py.AttributeError("message attribute was deleted");
+ }
+
+ Py.DeprecationWarning("BaseException.message has been deprecated as of Python 2.6");
+ return this.message;
+ }
+
+ @ExposedSet(name = "message")
+ public void setMessage(PyObject value) {
+ getDict().__setitem__("message", value);
+ }
+
@ExposedDelete(name = "message")
public void delMessage() {
- message = Py.None;
+ if (__dict__ != null && (message = __dict__.__finditem__("message")) != null) {
+ __dict__.__delitem__("message");
+ message = null;
+ }
}
}
Modified: trunk/jython/src/org/python/core/PyException.java
===================================================================
--- trunk/jython/src/org/python/core/PyException.java 2011-03-20 19:43:03 UTC (rev 7252)
+++ trunk/jython/src/org/python/core/PyException.java 2011-03-20 19:56:03 UTC (rev 7253)
@@ -194,9 +194,7 @@
type = type.__getitem__(0);
}
- if (type.getType() == PyString.TYPE) {
- Py.warning(Py.DeprecationWarning, "raising a string exception is deprecated");
- } else if (isExceptionClass(type)) {
+ if (isExceptionClass(type)) {
PyException pye = new PyException(type, value, (PyTraceback)traceback);
pye.normalize();
return pye;
@@ -212,10 +210,14 @@
} else {
// Not something you can raise. You get an exception
// anyway, just not what you specified :-)
- throw Py.TypeError("exceptions must be classes, instances, or strings (deprecated), "
- + "not " + type.getType().fastGetName());
+ throw Py.TypeError("exceptions must be old-style classes or derived from "
+ + "BaseException, not " + type.getType().fastGetName());
}
+ if (Options.py3kwarning && type instanceof PyClass) {
+ Py.DeprecationWarning("exceptions must derive from BaseException in 3.x");
+ }
+
return new PyException(type, value, (PyTraceback)traceback);
}
@@ -255,7 +257,13 @@
}
if (isExceptionClass(type) && isExceptionClass(exc)) {
- return Py.isSubClass(type, exc);
+ try {
+ return Py.isSubClass(type, exc);
+ } catch (PyException pye) {
+ // This function must not fail, so print the error here
+ Py.writeUnraisable(pye, type);
+ return false;
+ }
}
return type == exc;
Modified: trunk/jython/src/org/python/core/exceptions.java
===================================================================
--- trunk/jython/src/org/python/core/exceptions.java 2011-03-20 19:43:03 UTC (rev 7252)
+++ trunk/jython/src/org/python/core/exceptions.java 2011-03-20 19:56:03 UTC (rev 7253)
@@ -133,10 +133,12 @@
buildClass(dict, "MemoryError", "StandardError", "Out of memory.");
+ buildClass(dict, "BufferError", "StandardError", "Buffer error.");
+
buildClass(dict, "StopIteration", "Exception",
"Signal the end from iterator.next().");
- buildClass(dict, "GeneratorExit", "Exception", "Request that a generator exit.");
+ buildClass(dict, "GeneratorExit", "BaseException", "Request that a generator exit.");
buildClass(dict, "Warning", "Exception", "Base class for warning categories.");
@@ -166,10 +168,10 @@
buildClass(dict, "UnicodeWarning", "Warning",
"Base class for warnings about Unicode related problems, mostly\n"
+ "related to conversion problems.");
-
+
buildClass(dict, "BytesWarning", "Warning",
"Base class for warnings about bytes and buffer related problems, mostly\n"
- + "related to conversion from str or comparing to str.");
+ + "related to conversion from str or comparing to str.");
// Initialize ZipImportError here, where it's safe to; it's
// needed immediately
@@ -373,14 +375,16 @@
public static PyString UnicodeDecodeError__str__(PyObject self, PyObject[] args,
String[] kwargs) {
- int start = getStart(self, false);
- int end = getEnd(self, false);
- PyObject encoding = self.__getattr__("encoding");
- PyObject reason = self.__getattr__("reason");
+ int start = self.__getattr__("start").asInt();
+ int end = self.__getattr__("end").asInt();
+ // Get reason and encoding as strings, which they might not be if they've been
+ // modified after we were contructed
+ PyObject reason = self.__getattr__("reason").__str__();
+ PyObject encoding = self.__getattr__("encoding").__str__();
+ PyObject object = getString(self.__getattr__("object"), "object");
String result;
- if (end == (start + 1)) {
- PyObject object = self.__getattr__("object");
+ if (start < object.__len__() && end == (start + 1)) {
int badByte = (object.toString().charAt(start)) & 0xff;
result = String.format("'%.400s' codec can't decode byte 0x%x in position %d: %.400s",
encoding, badByte, start, reason);
@@ -406,14 +410,16 @@
public static PyString UnicodeEncodeError__str__(PyObject self, PyObject[] args,
String[] kwargs) {
- int start = getStart(self, true);
- int end = getEnd(self, true);
- PyObject encoding = self.__getattr__("encoding");
- PyObject reason = self.__getattr__("reason");
+ int start = self.__getattr__("start").asInt();
+ int end = self.__getattr__("end").asInt();
+ // Get reason and encoding as strings, which they might not be if they've been
+ // modified after we were contructed
+ PyObject reason = self.__getattr__("reason").__str__();
+ PyObject encoding = self.__getattr__("encoding").__str__();
+ PyObject object = getUnicode(self.__getattr__("object"), "object");
String result;
- if (end == (start + 1)) {
- PyObject object = self.__getattr__("object");
+ if (start < object.__len__() && end == (start + 1)) {
int badchar = object.toString().codePointAt(start);
String badcharStr;
if (badchar <= 0xff) {
@@ -455,13 +461,16 @@
public static PyString UnicodeTranslateError__str__(PyObject self, PyObject[] args,
String[] kwargs) {
- int start = getStart(self, true);
- int end = getEnd(self, true);
- PyObject reason = self.__getattr__("reason");
+ int start = self.__getattr__("start").asInt();
+ int end = self.__getattr__("end").asInt();
+ // Get reason as a string, which it might not be if it's been modified after we
+ // were contructed
+ PyObject reason = self.__getattr__("reason").__str__();
+ PyObject object = getUnicode(self.__getattr__("object"), "object");
String result;
- if (end == (start + 1)) {
- int badchar = (self.__getattr__("object").toString().codePointAt(start));
+ if (start < object.__len__() && end == (start + 1)) {
+ int badchar = object.toString().codePointAt(start);
String badCharStr;
if (badchar <= 0xff) {
badCharStr = String.format("x%02x", badchar);
@@ -488,7 +497,7 @@
* @return an the start position
*/
public static int getStart(PyObject self, boolean unicode) {
- int start = getInt(self.__getattr__("start"), "start");
+ int start = self.__getattr__("start").asInt();
PyObject object;
if (unicode) {
object = getUnicode(self.__getattr__("object"), "object");
@@ -513,7 +522,7 @@
* @return an the end position
*/
public static int getEnd(PyObject self, boolean unicode) {
- int end = getInt(self.__getattr__("end"), "end");
+ int end = self.__getattr__("end").asInt();
PyObject object;
if (unicode) {
object = getUnicode(self.__getattr__("object"), "object");
@@ -530,22 +539,6 @@
}
/**
- * Parse an int value for UnicodeErrors
- *
- * @param attr a PyObject
- * @param name of the attribute
- * @return an int value
- */
- public static int getInt(PyObject attr, String name) {
- if (attr instanceof PyInteger) {
- return ((PyInteger)attr).asInt();
- } else if (attr instanceof PyLong) {
- return ((PyLong)attr).asInt();
- }
- throw Py.TypeError(String.format("%.200s attribute must be int", name));
- }
-
- /**
* Ensure a PyString value for UnicodeErrors
*
* @param attr a PyObject
@@ -553,7 +546,7 @@
* @return an PyString
*/
public static PyString getString(PyObject attr, String name) {
- if (!(attr instanceof PyString)) {
+ if (!Py.isInstance(attr, PyString.TYPE)) {
throw Py.TypeError(String.format("%.200s attribute must be str", name));
}
return (PyString)attr;
@@ -663,10 +656,12 @@
this.javaMethod = javaMethod;
}
+ @Override
public PyBuiltinCallable bind(PyObject self) {
return new BoundStaticJavaMethod(getType(), self, info, javaMethod);
}
+ @Override
public PyObject __get__(PyObject obj, PyObject type) {
if (obj != null) {
return bind(obj);
@@ -674,6 +669,7 @@
return makeDescriptor((PyType)type);
}
+ @Override
public PyObject __call__(PyObject[] args, String kwargs[]) {
try {
return Py.java2py(javaMethod.invoke(null, self, args, kwargs));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-20 19:43:09
|
Revision: 7252
http://jython.svn.sourceforge.net/jython/?rev=7252&view=rev
Author: pjenvey
Date: 2011-03-20 19:43:03 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
reuse exceptions.getEnd
Modified Paths:
--------------
trunk/jython/src/org/python/core/codecs.java
Modified: trunk/jython/src/org/python/core/codecs.java
===================================================================
--- trunk/jython/src/org/python/core/codecs.java 2011-03-20 19:41:31 UTC (rev 7251)
+++ trunk/jython/src/org/python/core/codecs.java 2011-03-20 19:43:03 UTC (rev 7252)
@@ -252,23 +252,17 @@
public static PyObject replace_errors(PyObject[] args, String[] kws) {
ArgParser ap = new ArgParser("replace_errors", args, kws, "exc");
PyObject exc = ap.getPyObject(0);
- if (Py.isInstance(exc, Py.UnicodeDecodeError)) {
- PyObject object = exc.__getattr__("object");
- if (!Py.isInstance(object, PyString.TYPE) || Py.isInstance(object, PyUnicode.TYPE)) {
- throw Py.TypeError("object attribute must be str");
- }
- PyObject end = exc.__getattr__("end");
- return new PyTuple(new PyUnicode(Py_UNICODE_REPLACEMENT_CHARACTER), end);
- } else if (Py.isInstance(exc, Py.UnicodeEncodeError)) {
- PyObject object = exc.__getattr__("object");
- if (!Py.isInstance(object, PyUnicode.TYPE)) {
- throw Py.TypeError("object attribute must be unicode");
- }
- PyObject end = exc.__getattr__("end");
- return new PyTuple(Py.java2py("?"), end);
+ if (Py.isInstance(exc, Py.UnicodeEncodeError)) {
+ int end = exceptions.getEnd(exc, true);
+ return new PyTuple(new PyUnicode("?"), Py.newInteger(end));
+ } else if (Py.isInstance(exc, Py.UnicodeDecodeError)) {
+ int end = exceptions.getEnd(exc, false);
+ return new PyTuple(new PyUnicode(Py_UNICODE_REPLACEMENT_CHARACTER),
+ Py.newInteger(end));
} else if (Py.isInstance(exc, Py.UnicodeTranslateError)) {
- PyObject end = exc.__getattr__("end");
- return new PyTuple(new PyUnicode(Py_UNICODE_REPLACEMENT_CHARACTER), end);
+ int end = exceptions.getEnd(exc, true);
+ return new PyTuple(new PyUnicode(Py_UNICODE_REPLACEMENT_CHARACTER),
+ Py.newInteger(end));
}
throw wrong_exception_type(exc);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-20 19:41:37
|
Revision: 7251
http://jython.svn.sourceforge.net/jython/?rev=7251&view=rev
Author: pjenvey
Date: 2011-03-20 19:41:31 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
o add Py.writeUnraisable
o remove the no longer needed formatException <oldclass>.__module__ workaround
o cleanup class/instance __repr__
Modified Paths:
--------------
trunk/jython/src/org/python/core/Py.java
trunk/jython/src/org/python/core/PyClass.java
trunk/jython/src/org/python/core/PyFinalizableInstance.java
trunk/jython/src/org/python/core/PyInstance.java
trunk/jython/src/org/python/modules/_weakref/AbstractReference.java
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2011-03-20 06:07:17 UTC (rev 7250)
+++ trunk/jython/src/org/python/core/Py.java 2011-03-20 19:41:31 UTC (rev 7251)
@@ -1168,6 +1168,10 @@
}
public static String formatException(PyObject type, PyObject value) {
+ return formatException(type, value, false);
+ }
+
+ public static String formatException(PyObject type, PyObject value, boolean useRepr) {
StringBuilder buf = new StringBuilder();
if (PyException.isExceptionClass(type)) {
@@ -1178,10 +1182,7 @@
}
PyObject moduleName = type.__findattr__("__module__");
if (moduleName == null) {
- // XXX: Workaround the fact that PyClass lacks __module__
- if (!(type instanceof PyClass)) {
- buf.append("<unknown>");
- }
+ buf.append("<unknown>");
} else {
String moduleStr = moduleName.toString();
if (!moduleStr.equals("exceptions")) {
@@ -1191,11 +1192,11 @@
}
buf.append(className);
} else {
- buf.append(type.__str__());
+ buf.append(useRepr ? type.__repr__() : type.__str__());
}
if (value != null && value != Py.None) {
// only print colon if the str() of the object is not the empty string
- PyObject s = value.__str__();
+ PyObject s = useRepr ? value.__repr__() : value.__str__();
if (!(s instanceof PyString) || s.__len__() != 0) {
buf.append(": ");
}
@@ -1204,7 +1205,18 @@
return buf.toString();
}
+ public static void writeUnraisable(Exception exc, PyObject obj) {
+ if (exc instanceof PyException) {
+ PyException pye = (PyException) exc;
+ stderr.println(String.format("Exception %s in %s ignored",
+ formatException(pye.type, pye.value, true), obj));
+ } else {
+ // XXX: this could be better handled
+ exc.printStackTrace();
+ }
+ }
+
/* Equivalent to Python's assert statement */
public static void assert_(PyObject test, PyObject message) {
if (!test.__nonzero__()) {
Modified: trunk/jython/src/org/python/core/PyClass.java
===================================================================
--- trunk/jython/src/org/python/core/PyClass.java 2011-03-20 06:07:17 UTC (rev 7250)
+++ trunk/jython/src/org/python/core/PyClass.java 2011-03-20 19:41:31 UTC (rev 7251)
@@ -229,13 +229,8 @@
@Override
public String toString() {
PyObject mod = __dict__.__finditem__("__module__");
- String smod;
- if (mod == null || !(mod instanceof PyString)) {
- smod = "<unknown>";
- } else {
- smod = ((PyString) mod).toString();
- }
- return "<class " + smod + "." + __name__ + " at " + Py.idstr(this) + ">";
+ String modStr = (mod == null || !Py.isInstance(mod, PyString.TYPE)) ? "?" : mod.toString();
+ return String.format("<class %s.%s at %s>", modStr, __name__, Py.idstr(this));
}
public boolean isSubClass(PyClass superclass) {
Modified: trunk/jython/src/org/python/core/PyFinalizableInstance.java
===================================================================
--- trunk/jython/src/org/python/core/PyFinalizableInstance.java 2011-03-20 06:07:17 UTC (rev 7250)
+++ trunk/jython/src/org/python/core/PyFinalizableInstance.java 2011-03-20 19:41:31 UTC (rev 7251)
@@ -12,14 +12,14 @@
* This is a special class due to performance. Defining
* finalize() on a class, makes the class a lot slower.
*/
+public class PyFinalizableInstance extends PyInstance {
-public class PyFinalizableInstance extends PyInstance
-{
public PyFinalizableInstance(PyClass iclass) {
super(iclass);
}
// __del__ method is invoked upon object finalization.
+ @Override
protected void finalize() {
try {
instclass.__del__.__call__(this);
@@ -28,12 +28,10 @@
PyObject method = instclass.__del__;
try {
method = __findattr__("__del__");
- } catch (PyException e) { ; }
-
- Py.stderr.println("Exception " +
- Py.formatException(exc.type, exc.value) +
- " in " + method +
- " ignored");
+ } catch (PyException e) {
+ // nothing we can do
+ }
+ Py.writeUnraisable(exc, method);
}
}
}
Modified: trunk/jython/src/org/python/core/PyInstance.java
===================================================================
--- trunk/jython/src/org/python/core/PyInstance.java 2011-03-20 06:07:17 UTC (rev 7250)
+++ trunk/jython/src/org/python/core/PyInstance.java 2011-03-20 19:41:31 UTC (rev 7251)
@@ -381,18 +381,9 @@
*/
protected PyString makeDefaultRepr() {
PyObject mod = instclass.__dict__.__finditem__("__module__");
- String smod;
- if(mod == Py.None) {
- smod = "";
- } else {
- if(mod == null || !(mod instanceof PyString)) {
- smod = "<unknown>.";
- } else {
- smod = ((PyString)mod).toString() + '.';
- }
- }
- return new PyString("<" + smod + instclass.__name__ + " instance at " +
- Py.idstr(this) + ">");
+ String modStr = (mod == null || !Py.isInstance(mod, PyString.TYPE)) ? "?" : mod.toString();
+ return new PyString(String.format("<%s.%s instance at %s>", modStr, instclass.__name__,
+ Py.idstr(this)));
}
@Override
Modified: trunk/jython/src/org/python/modules/_weakref/AbstractReference.java
===================================================================
--- trunk/jython/src/org/python/modules/_weakref/AbstractReference.java 2011-03-20 06:07:17 UTC (rev 7250)
+++ trunk/jython/src/org/python/modules/_weakref/AbstractReference.java 2011-03-20 19:41:31 UTC (rev 7251)
@@ -27,9 +27,7 @@
try {
callback.__call__(this);
} catch (Exception exc) {
- // XXX: Should trigger the equiv. of CPython's
- // PyErr_WriteUnraisable
- exc.printStackTrace();
+ Py.writeUnraisable(exc, callback);
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-20 06:07:23
|
Revision: 7250
http://jython.svn.sourceforge.net/jython/?rev=7250&view=rev
Author: pjenvey
Date: 2011-03-20 06:07:17 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
hg version support
Modified Paths:
--------------
trunk/jython/build.xml
trunk/jython/src/org/python/Version.java
trunk/jython/src/org/python/core/PySystemState.java
Modified: trunk/jython/build.xml
===================================================================
--- trunk/jython/build.xml 2011-03-19 23:41:41 UTC (rev 7249)
+++ trunk/jython/build.xml 2011-03-20 06:07:17 UTC (rev 7250)
@@ -398,10 +398,33 @@
<exec executable="svnversion" failifexecutionfails="false" outputproperty="build.svn.revision"/>
</target>
+ <!-- XXX: Might this work on Windows? -->
+ <target name="hg-branch" if="os.family.unix">
+ <exec executable="hg" failifexecutionfails="false" outputproperty="build.hg.branch">
+ <arg line="id -b"/>
+ </exec>
+ </target>
+ <target name="hg-tag" if="os.family.unix">
+ <exec executable="hg" failifexecutionfails="false" outputproperty="build.hg.tag">
+ <arg line="id -t"/>
+ </exec>
+ </target>
+ <target name="hg-version" if="os.family.unix">
+ <exec executable="hg" failifexecutionfails="false" outputproperty="build.hg.version">
+ <arg line="id -i"/>
+ </exec>
+ </target>
+ <target name="hg-id" depends="hg-branch, hg-tag, hg-version"/>
+
<!-- skip-brand can be set in ant.properties or as a system property to keep from updating the
version.properties file and making the jar on every developer build. -->
+ <!-- when hg:
+ <target name="brand-version" depends="init, hg-id" unless="skip-brand">-->
<target name="brand-version" depends="init, svnversion" unless="skip-brand">
<property name="build.svn.revision" value=""/>
+ <property name="build.hg.branch" value=""/>
+ <property name="build.hg.tag" value=""/>
+ <property name="build.hg.version" value=""/>
<tstamp>
<format property="build.date" pattern="MMM d yyyy" offset="0"/>
<format property="build.time" pattern="HH:mm:ss" offset="0"/>
@@ -416,7 +439,10 @@
jython.release_serial=${jython.release_serial}
jython.build.date=${build.date}
jython.build.time=${build.time}
-jython.build.svn_revision=${build.svn.revision}</echo>
+jython.build.svn_revision=${build.svn.revision}
+jython.build.hg_branch=${build.hg.branch}
+jython.build.hg_tag=${build.hg.tag}
+jython.build.hg_version=${build.hg.version}</echo>
</target>
<target name="brand-readme-version" depends="checkout" if="do.snapshot.build">
Modified: trunk/jython/src/org/python/Version.java
===================================================================
--- trunk/jython/src/org/python/Version.java 2011-03-19 23:41:41 UTC (rev 7249)
+++ trunk/jython/src/org/python/Version.java 2011-03-20 06:07:17 UTC (rev 7250)
@@ -34,6 +34,8 @@
public static String DATE;
public static String TIME;
public static String SVN_REVISION;
+ /** Current hg global revision id (hg id -i). */
+ public static String HG_VERSION;
/** Determined from headURL, branch is the path under the
* subversion root, e.g. branches/asm. */
@@ -42,6 +44,12 @@
/** Short version of branch, e.g. asm. */
public static String SHORT_BRANCH;
+ /** Current hg branch (hg id -b). */
+ public static String HG_BRANCH;
+
+ /** Current hg tag (hg id -t), e.g. 'tip'. */
+ public static String HG_TAG;
+
/** The flags that are set by default in a code object. */
private static final Collection<CodeFlag> defaultCodeFlags = Arrays.asList(
CodeFlag.CO_NESTED, CodeFlag.CO_GENERATOR_ALLOWED, CodeFlag.CO_FUTURE_WITH_STATEMENT);
@@ -103,6 +111,9 @@
DATE = properties.getProperty("jython.build.date");
TIME = properties.getProperty("jython.build.time");
SVN_REVISION = properties.getProperty("jython.build.svn_revision");
+ HG_BRANCH = properties.getProperty("jython.build.hg_branch");
+ HG_TAG = properties.getProperty("jython.build.hg_tag");
+ HG_VERSION = properties.getProperty("jython.build.hg_version");
} catch (IOException ioe) {
System.err.println("There was a problem loading ".concat(versionProperties)
.concat(":"));
@@ -137,6 +148,21 @@
}
/**
+ * Return the current hg version number. May be an empty string on environments that
+ * can't determine it.
+ */
+ public static String getHGVersion() {
+ return HG_VERSION;
+ }
+
+ /**
+ * Return the current hg identifier name, either the current branch or tag.
+ */
+ public static String getHGIdentifier() {
+ return "".equals(HG_TAG) || "tip".equals(HG_TAG) ? HG_BRANCH : HG_TAG;
+ }
+
+ /**
* Return the current build information, including revision and
* timestamp.
*/
@@ -148,6 +174,16 @@
}
/**
+ * Return the current build information, including revision and timestamp.
+ */
+ public static String getBuildInfoHG() {
+ String revision = getHGVersion();
+ String sep = "".equals(revision) ? "" : ":";
+ String hgId = getHGIdentifier();
+ return String.format("%s%s%s, %.20s, %.9s", hgId, sep, revision, DATE, TIME);
+ }
+
+ /**
* Describe the current Java VM.
*/
public static String getVM() {
Modified: trunk/jython/src/org/python/core/PySystemState.java
===================================================================
--- trunk/jython/src/org/python/core/PySystemState.java 2011-03-19 23:41:41 UTC (rev 7249)
+++ trunk/jython/src/org/python/core/PySystemState.java 2011-03-20 06:07:17 UTC (rev 7250)
@@ -75,6 +75,8 @@
public final static Class flags = Options.class;
public static PyTuple subversion;
+
+ public static PyTuple _mercurial;
/**
* The copyright notice for this release.
*/
@@ -956,6 +958,8 @@
Py.newInteger(Version.PY_RELEASE_SERIAL));
subversion = new PyTuple(Py.newString("Jython"), Py.newString(Version.BRANCH),
Py.newString(Version.SVN_REVISION));
+ _mercurial = new PyTuple(Py.newString("Jython"), Py.newString(Version.getHGIdentifier()),
+ Py.newString(Version.getHGVersion()));
}
public static boolean isPackageCacheEnabled() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-19 23:41:47
|
Revision: 7249
http://jython.svn.sourceforge.net/jython/?rev=7249&view=rev
Author: pjenvey
Date: 2011-03-19 23:41:41 +0000 (Sat, 19 Mar 2011)
Log Message:
-----------
simplify
Modified Paths:
--------------
trunk/jython/src/org/python/core/PyFloat.java
Modified: trunk/jython/src/org/python/core/PyFloat.java
===================================================================
--- trunk/jython/src/org/python/core/PyFloat.java 2011-03-19 20:47:21 UTC (rev 7248)
+++ trunk/jython/src/org/python/core/PyFloat.java 2011-03-19 23:41:41 UTC (rev 7249)
@@ -81,7 +81,7 @@
@ExposedGet(name = "real", doc = BuiltinDocs.float_real_doc)
public PyObject getReal() {
- return getType() == TYPE ? this : new PyFloat(value);
+ return float___float__();
}
@ExposedGet(name = "imag", doc = BuiltinDocs.float_imag_doc)
@@ -684,10 +684,7 @@
@ExposedMethod(doc = BuiltinDocs.float___float___doc)
final PyFloat float___float__() {
- if (getType() == TYPE) {
- return this;
- }
- return Py.newFloat(getValue());
+ return getType() == TYPE ? this : Py.newFloat(getValue());
}
@Override
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-19 20:47:27
|
Revision: 7248
http://jython.svn.sourceforge.net/jython/?rev=7248&view=rev
Author: pjenvey
Date: 2011-03-19 20:47:21 +0000 (Sat, 19 Mar 2011)
Log Message:
-----------
add real/imag/numerator/denominator where applicable to the numbers
Modified Paths:
--------------
trunk/jython/src/org/python/core/PyComplex.java
trunk/jython/src/org/python/core/PyFloat.java
trunk/jython/src/org/python/core/PyInteger.java
trunk/jython/src/org/python/core/PyLong.java
Modified: trunk/jython/src/org/python/core/PyComplex.java
===================================================================
--- trunk/jython/src/org/python/core/PyComplex.java 2011-03-19 20:39:47 UTC (rev 7247)
+++ trunk/jython/src/org/python/core/PyComplex.java 2011-03-19 20:47:21 UTC (rev 7248)
@@ -707,10 +707,7 @@
@ExposedMethod(doc = BuiltinDocs.complex___pos___doc)
final PyObject complex___pos__() {
- if (getType() == TYPE) {
- return this;
- }
- return new PyComplex(real, imag);
+ return getType() == TYPE ? this : new PyComplex(real, imag);
}
@Override
Modified: trunk/jython/src/org/python/core/PyFloat.java
===================================================================
--- trunk/jython/src/org/python/core/PyFloat.java 2011-03-19 20:39:47 UTC (rev 7247)
+++ trunk/jython/src/org/python/core/PyFloat.java 2011-03-19 20:47:21 UTC (rev 7248)
@@ -8,6 +8,7 @@
import java.math.BigDecimal;
import org.python.expose.ExposedClassMethod;
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -78,6 +79,16 @@
}
}
+ @ExposedGet(name = "real", doc = BuiltinDocs.float_real_doc)
+ public PyObject getReal() {
+ return getType() == TYPE ? this : new PyFloat(value);
+ }
+
+ @ExposedGet(name = "imag", doc = BuiltinDocs.float_imag_doc)
+ public PyObject getImag() {
+ return Py.newFloat(0.0);
+ }
+
/**
* Determine if this float is not infinity, nor NaN.
*/
Modified: trunk/jython/src/org/python/core/PyInteger.java
===================================================================
--- trunk/jython/src/org/python/core/PyInteger.java 2011-03-19 20:39:47 UTC (rev 7247)
+++ trunk/jython/src/org/python/core/PyInteger.java 2011-03-19 20:47:21 UTC (rev 7248)
@@ -7,6 +7,7 @@
import java.io.Serializable;
import java.math.BigInteger;
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -105,6 +106,26 @@
}
}
+ @ExposedGet(name = "real", doc = BuiltinDocs.int_real_doc)
+ public PyObject getReal() {
+ return int___int__();
+ }
+
+ @ExposedGet(name = "imag", doc = BuiltinDocs.int_imag_doc)
+ public PyObject getImag() {
+ return Py.newInteger(0);
+ }
+
+ @ExposedGet(name = "numerator", doc = BuiltinDocs.int_numerator_doc)
+ public PyObject getNumerator() {
+ return int___int__();
+ }
+
+ @ExposedGet(name = "denominator", doc = BuiltinDocs.int_denominator_doc)
+ public PyObject getDenominator() {
+ return Py.newInteger(1);
+ }
+
public int getValue() {
return value;
}
@@ -814,10 +835,7 @@
@ExposedMethod(doc = BuiltinDocs.int___int___doc)
final PyInteger int___int__() {
- if (getType() == TYPE) {
- return this;
- }
- return Py.newInteger(getValue());
+ return getType() == TYPE ? this : Py.newInteger(getValue());
}
@Override
Modified: trunk/jython/src/org/python/core/PyLong.java
===================================================================
--- trunk/jython/src/org/python/core/PyLong.java 2011-03-19 20:39:47 UTC (rev 7247)
+++ trunk/jython/src/org/python/core/PyLong.java 2011-03-19 20:47:21 UTC (rev 7248)
@@ -8,6 +8,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -129,6 +130,26 @@
return new BigDecimal(value).toBigInteger();
}
+ @ExposedGet(name = "real", doc = BuiltinDocs.long_real_doc)
+ public PyObject getReal() {
+ return long___long__();
+ }
+
+ @ExposedGet(name = "imag", doc = BuiltinDocs.long_imag_doc)
+ public PyObject getImag() {
+ return Py.newLong(0);
+ }
+
+ @ExposedGet(name = "numerator", doc = BuiltinDocs.long_numerator_doc)
+ public PyObject getNumerator() {
+ return long___long__();
+ }
+
+ @ExposedGet(name = "denominator", doc = BuiltinDocs.long_denominator_doc)
+ public PyObject getDenominator() {
+ return Py.newLong(1);
+ }
+
@Override
public String toString() {
return long_toString();
@@ -876,10 +897,7 @@
@ExposedMethod(doc = BuiltinDocs.long___long___doc)
final PyObject long___long__() {
- if (getType() == TYPE) {
- return this;
- }
- return Py.newLong(getValue());
+ return getType() == TYPE ? this : Py.newLong(getValue());
}
@Override
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-19 20:39:54
|
Revision: 7247
http://jython.svn.sourceforge.net/jython/?rev=7247&view=rev
Author: pjenvey
Date: 2011-03-19 20:39:47 +0000 (Sat, 19 Mar 2011)
Log Message:
-----------
reapply r5601 to warnings.py, correctly fix filename from the compiled filename
Modified Paths:
--------------
trunk/jython/Lib/warnings.py
Modified: trunk/jython/Lib/warnings.py
===================================================================
--- trunk/jython/Lib/warnings.py 2011-03-19 20:03:20 UTC (rev 7246)
+++ trunk/jython/Lib/warnings.py 2011-03-19 20:39:47 UTC (rev 7247)
@@ -187,6 +187,8 @@
fnl = filename.lower()
if fnl.endswith((".pyc", ".pyo")):
filename = filename[:-1]
+ elif fnl.endswith("$py.class"):
+ filename = filename[:-9] + '.py'
else:
if module == "__main__":
try:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-19 20:03:26
|
Revision: 7246
http://jython.svn.sourceforge.net/jython/?rev=7246&view=rev
Author: pjenvey
Date: 2011-03-19 20:03:20 +0000 (Sat, 19 Mar 2011)
Log Message:
-----------
add -3 and Py.warnPy3k
Modified Paths:
--------------
trunk/jython/src/org/python/core/Options.java
trunk/jython/src/org/python/core/Py.java
trunk/jython/src/org/python/core/PySystemState.java
trunk/jython/src/org/python/util/jython.java
Modified: trunk/jython/src/org/python/core/Options.java
===================================================================
--- trunk/jython/src/org/python/core/Options.java 2011-03-18 02:25:16 UTC (rev 7245)
+++ trunk/jython/src/org/python/core/Options.java 2011-03-19 20:03:20 UTC (rev 7246)
@@ -75,6 +75,9 @@
/** Force stdin, stdout and stderr to be unbuffered, and opened in
* binary mode */
public static boolean unbuffered = false;
+
+ /** Whether -3 (py3k warnings) were enabled via the command line. */
+ public static boolean py3kwarning = false;
//XXX: place holder
public static int bytes_warning = 0;
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2011-03-18 02:25:16 UTC (rev 7245)
+++ trunk/jython/src/org/python/core/Py.java 2011-03-19 20:03:20 UTC (rev 7246)
@@ -410,6 +410,16 @@
warning(BytesWarning, message);
}
+ public static void warnPy3k(String message) {
+ warnPy3k(message, 1);
+ }
+
+ public static void warnPy3k(String message, int stacklevel) {
+ if (Options.py3kwarning) {
+ warning(DeprecationWarning, message, stacklevel);
+ }
+ }
+
private static PyObject warnings_mod;
private static PyObject importWarnings() {
@@ -438,6 +448,10 @@
}
public static void warning(PyObject category, String message) {
+ warning(category, message, 1);
+ }
+
+ public static void warning(PyObject category, String message, int stacklevel) {
PyObject func = null;
PyObject mod = importWarnings();
if (mod != null) {
@@ -447,7 +461,7 @@
System.err.println(warn_hcategory(category) + ": " + message);
return;
} else {
- func.__call__(Py.newString(message), category);
+ func.__call__(Py.newString(message), category, Py.newInteger(stacklevel));
}
}
Modified: trunk/jython/src/org/python/core/PySystemState.java
===================================================================
--- trunk/jython/src/org/python/core/PySystemState.java 2011-03-18 02:25:16 UTC (rev 7245)
+++ trunk/jython/src/org/python/core/PySystemState.java 2011-03-19 20:03:20 UTC (rev 7246)
@@ -70,8 +70,7 @@
// for tests that would need to pass but today would not.
public final static int maxsize = Integer.MAX_VALUE;
- //XXX: place holder
- public final static boolean py3kwarning = false;
+ public static boolean py3kwarning = false;
public final static Class flags = Options.class;
@@ -190,6 +189,7 @@
currentWorkingDir = new File("").getAbsolutePath();
+ py3kwarning = Options.py3kwarning;
// Set up the initial standard ins and outs
String mode = Options.unbuffered ? "b" : "";
int buffering = Options.unbuffered ? 0 : 1;
Modified: trunk/jython/src/org/python/util/jython.java
===================================================================
--- trunk/jython/src/org/python/util/jython.java 2011-03-18 02:25:16 UTC (rev 7245)
+++ trunk/jython/src/org/python/util/jython.java 2011-03-19 20:03:20 UTC (rev 7246)
@@ -39,6 +39,7 @@
private static final String usage = usageHeader +
"Options and arguments:\n" + //(and corresponding environment variables):\n" +
+ //"-B : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x\n" +
"-c cmd : program passed in as string (terminates option list)\n" +
//"-d : debug output from parser (also PYTHONDEBUG=x)\n" +
"-Dprop=v : Set the property `prop' to value `v'\n"+
@@ -52,14 +53,18 @@
//"-O : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n" +
//"-OO : remove doc-strings in addition to the -O optimizations\n" +
"-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n" +
+ // XXX: support -s
+ //"-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n" +
"-S : don't imply 'import site' on initialization\n" +
//"-t : issue warnings about inconsistent tab usage (-tt: issue errors)\n" +
"-u : unbuffered binary stdout and stderr\n" + // (also PYTHONUNBUFFERED=x)\n" +
//" see man page for details on internal buffering relating to '-u'\n" +
"-v : verbose (trace import statements)\n" + // (also PYTHONVERBOSE=x)\n" +
+ " can be supplied multiple times to increase verbosity\n" +
"-V : print the Python version number and exit (also --version)\n" +
"-W arg : warning control (arg is action:message:category:module:lineno)\n" +
//"-x : skip first line of source, allowing use of non-Unix forms of #!cmd\n" +
+ "-3 : warn about Python 3.x incompatibilities that 2to3 cannot trivially fix\n" +
"file : program read from script file\n" +
"- : program read from stdin (default; interactive mode if a tty)\n" +
"arg ... : arguments passed to program in sys.argv[1:]\n" +
@@ -498,6 +503,8 @@
argv[i] = args[index];
}
return true;
+ } else if (arg.startsWith("-3")) {
+ Options.py3kwarning = true;
} else {
String opt = args[index];
if (opt.startsWith("--")) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-18 02:25:23
|
Revision: 7245
http://jython.svn.sourceforge.net/jython/?rev=7245&view=rev
Author: pjenvey
Date: 2011-03-18 02:25:16 +0000 (Fri, 18 Mar 2011)
Log Message:
-----------
o add abc support. we differ from CPython in that type lacks the
__instance/subclasscheck__ methods as it would slow down isinstance/subclass
o somewhat fix our object.__init__/__new__ FIXMEs and disallow arbitrary args
to __new__ per 2.6. __init__ doesn't repeat this check yet but this is probably
enough
Modified Paths:
--------------
trunk/jython/src/org/python/core/Py.java
trunk/jython/src/org/python/core/PyObject.java
trunk/jython/src/org/python/core/PyType.java
Modified: trunk/jython/src/org/python/core/Py.java
===================================================================
--- trunk/jython/src/org/python/core/Py.java 2011-03-18 01:26:55 UTC (rev 7244)
+++ trunk/jython/src/org/python/core/Py.java 2011-03-18 02:25:16 UTC (rev 7245)
@@ -86,6 +86,8 @@
public static long TPFLAGS_HEAPTYPE = 1L << 9;
/** Set if the type allows subclassing */
public static long TPFLAGS_BASETYPE = 1L << 10;
+ /** Type is abstract and cannot be instantiated */
+ public static long TPFLAGS_IS_ABSTRACT = 1L << 20;
/** Builtin types that are used to setup PyObject. */
static final Set<Class<?>> BOOTSTRAP_TYPES = Generic.set();
@@ -1866,104 +1868,183 @@
new File(dir, name.substring(0, index)));
}
- private static boolean abstract_issubclass(PyObject derived, PyObject cls) {
- if (derived == cls) {
+ public static boolean isInstance(PyObject inst, PyObject cls) {
+ // Quick test for an exact match
+ if (inst.getType() == cls) {
return true;
}
- PyObject bases = derived.__findattr__("__bases__");
- if (bases == null) {
+
+ if (cls instanceof PyTuple) {
+ ThreadState threadState = Py.getThreadState();
+ threadState.enterRecursiveCall(" in __subclasscheck__");
+ try {
+ for (PyObject item : cls.asIterable()) {
+ if (isInstance(inst, item)) {
+ return true;
+ }
+ }
+ } finally {
+ threadState.leaveRecursiveCall();
+ }
return false;
}
- for (int i = 0; i < bases.__len__(); i++) {
- if (abstract_issubclass(bases.__getitem__(i), cls)) {
- return true;
- }
+
+ PyObject checkerResult;
+ if ((checkerResult = dispatchToChecker(inst, cls, "__instancecheck__")) != null) {
+ return checkerResult.__nonzero__();
}
- return false;
- }
- public static boolean isInstance(PyObject inst, PyObject cls) {
- return recursiveIsInstance(inst, cls, 0);
+ return recursiveIsInstance(inst, cls);
}
- private static boolean recursiveIsInstance(PyObject inst, PyObject cls, int recursionDepth) {
+ static boolean recursiveIsInstance(PyObject inst, PyObject cls) {
if (cls instanceof PyClass && inst instanceof PyInstance) {
- PyClass inClass = (PyClass)inst.fastGetClass();
- return inClass.isSubClass((PyClass)cls);
- } else if (cls instanceof PyType) {
+ PyClass inClass = ((PyInstance) inst).fastGetClass();
+ return inClass.isSubClass((PyClass) cls);
+ }
+ if (cls instanceof PyType) {
PyType instType = inst.getType();
- PyType type = (PyType)cls;
+ PyType type = (PyType) cls;
// equiv. to PyObject_TypeCheck
if (instType == type || instType.isSubType(type)) {
return true;
}
- PyObject c = inst.__findattr__("__class__");
- if (c != null && c != instType && c instanceof PyType) {
- return ((PyType)c).isSubType(type);
+ PyObject instCls = inst.__findattr__("__class__");
+ if (instCls != null && instCls != instType && instCls instanceof PyType) {
+ return ((PyType) instCls).isSubType(type);
}
return false;
- } else if (cls instanceof PyTuple) {
- if (recursionDepth > Py.getSystemState().getrecursionlimit()) {
- throw Py.RuntimeError("nest level of tuple too deep");
- }
+ }
+
+ checkClass(cls, "isinstance() arg 2 must be a class, type, or tuple of classes and types");
+ PyObject instCls = inst.__findattr__("__class__");
+ if (instCls == null) {
+ return false;
+ }
+ return abstractIsSubClass(instCls, cls);
+ }
- for (PyObject tupleItem : ((PyTuple)cls).getArray()) {
- if (recursiveIsInstance(inst, tupleItem, recursionDepth + 1)) {
- return true;
+ public static boolean isSubClass(PyObject derived, PyObject cls) {
+ if (cls instanceof PyTuple) {
+ ThreadState threadState = Py.getThreadState();
+ threadState.enterRecursiveCall(" in __subclasscheck__");
+ try {
+ for (PyObject item : cls.asIterable()) {
+ if (isSubClass(derived, item)) {
+ return true;
+ }
}
+ } finally {
+ threadState.leaveRecursiveCall();
}
return false;
- } else {
- if (cls.__findattr__("__bases__") == null) {
- throw Py.TypeError("isinstance() arg 2 must be a class, type, or tuple of "
- + "classes and types");
- }
+ }
- PyObject icls = inst.__findattr__("__class__");
- if (icls == null) {
- return false;
- }
- return abstract_issubclass(icls, cls);
+ PyObject checkerResult;
+ if ((checkerResult = dispatchToChecker(derived, cls, "__subclasscheck__")) != null) {
+ return checkerResult.__nonzero__();
}
- }
- public static boolean isSubClass(PyObject derived,PyObject cls) {
- return isSubClass(derived, cls, 0);
+ return recursiveIsSubClass(derived, cls);
}
- private static boolean isSubClass(PyObject derived, PyObject cls, int recursionDepth) {
+ static boolean recursiveIsSubClass(PyObject derived, PyObject cls) {
if (derived instanceof PyType && cls instanceof PyType) {
if (derived == cls) {
return true;
}
return ((PyType) derived).isSubType((PyType) cls);
- } else if (cls instanceof PyClass && derived instanceof PyClass) {
+ }
+ if (derived instanceof PyClass && cls instanceof PyClass) {
return ((PyClass) derived).isSubClass((PyClass) cls);
- } else if (cls.getClass() == PyTuple.class) {
- if (recursionDepth > Py.getSystemState().getrecursionlimit()) {
- throw Py.RuntimeError("nest level of tuple too deep");
+ }
+
+ checkClass(derived, "issubclass() arg 1 must be a class");
+ checkClass(cls, "issubclass() arg 2 must be a class or tuple of classes");
+ return abstractIsSubClass(derived, cls);
+ }
+
+ private static boolean abstractIsSubClass(PyObject derived, PyObject cls) {
+ while (true) {
+ if (derived == cls) {
+ return true;
}
- for (int i = 0; i < cls.__len__(); i++) {
- if (isSubClass(derived, cls.__getitem__(i), recursionDepth + 1)) {
+
+ PyTuple bases = abstractGetBases(derived);
+ if (bases == null) {
+ return false;
+ }
+
+ int basesSize = bases.size();
+ if (basesSize == 0) {
+ return false;
+ }
+ if (basesSize == 1) {
+ // Avoid recursivity in the single inheritance case
+ derived = bases.pyget(0);
+ continue;
+ }
+
+ for (PyObject base : bases.asIterable()) {
+ if (abstractIsSubClass(base, cls)) {
return true;
}
}
return false;
- } else {
- if (derived.__findattr__("__bases__") == null) {
- throw Py.TypeError(
- "issubclass() arg 1 must be a class");
- }
- if (cls.__findattr__("__bases__") == null) {
- throw Py.TypeError(
- "issubclass() arg 2 must be a class, type," + " or tuple of classes and types");
- }
- return abstract_issubclass(derived, cls);
}
}
+ /**
+ * Attempt to dispatch an isinstance/issubclass call to cls's associated
+ * __instance/subclasscheck__.
+ *
+ * @param checkerArg the argument to call the checker with
+ * @param cls a Python class
+ * @param checkerName the checker name
+ * @return null if cls provides no checker, otherwise the result of calling the
+ * checker
+ */
+ private static PyObject dispatchToChecker(PyObject checkerArg, PyObject cls,
+ String checkerName) {
+ PyObject checker = cls.__findattr__(checkerName);
+ if (checker == null) {
+ return null;
+ }
+
+ PyObject result;
+ ThreadState threadState = Py.getThreadState();
+ threadState.enterRecursiveCall(" in " + checkerName);
+ try {
+ result = checker.__call__(checkerArg);
+ } finally {
+ threadState.leaveRecursiveCall();
+ }
+ return result;
+ }
+
+ /**
+ * Return the __bases__ of cls. Returns null if no valid __bases__ are found.
+ */
+ private static PyTuple abstractGetBases(PyObject cls) {
+ PyObject bases = cls.__findattr__("__bases__");
+ if (bases instanceof PyTuple) {
+ return (PyTuple) bases;
+ }
+ return null;
+ }
+
+ /**
+ * Throw a TypeError with the specified message if cls does not appear to be a Python
+ * class.
+ */
+ private static void checkClass(PyObject cls, String message) {
+ if (abstractGetBases(cls) == null) {
+ throw Py.TypeError(message);
+ }
+ }
+
static PyObject[] make_array(PyObject iterable) {
// Special-case the common tuple and list cases, for efficiency
if (iterable instanceof PySequenceList) {
Modified: trunk/jython/src/org/python/core/PyObject.java
===================================================================
--- trunk/jython/src/org/python/core/PyObject.java 2011-03-18 01:26:55 UTC (rev 7244)
+++ trunk/jython/src/org/python/core/PyObject.java 2011-03-18 02:25:16 UTC (rev 7245)
@@ -8,6 +8,7 @@
import java.util.List;
import java.util.Map;
+import org.python.expose.ExposedClassMethod;
import org.python.expose.ExposedDelete;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -74,17 +75,32 @@
objtype = (PyType)this;
}
- //XXX: in CPython object.__new__ has a doc string...
@ExposedNew
+ static final PyObject object___new__(PyNewWrapper new_, boolean init, PyType subtype,
+ PyObject[] args, String[] keywords) {
+ // don't allow arguments if the default object.__init__() is about to be called
+ PyObject[] where = new PyObject[1];
+ subtype.lookup_where("__init__", where);
+ if (where[0] == TYPE && args.length > 0) {
+ throw Py.TypeError("object.__new__() takes no parameters");
+ }
+
+ if (subtype.isAbstract()) {
+ // Compute ", ".join(sorted(type.__abstractmethods__)) into methods
+ PyObject sorted =
+ Py.getSystemState().getBuiltins().__getitem__(Py.newString("sorted"));
+ PyString methods =
+ Py.newString(", ")
+ .join(sorted.__call__(subtype.getAbstractmethods()));
+ throw Py.TypeError(String.format("Can't instantiate abstract class %s with abstract "
+ + "methods %s", subtype.fastGetName(), methods));
+ }
+
+ return new_.for_type == subtype ? new PyObject() : new PyObjectDerived(subtype);
+ }
+
@ExposedMethod(doc = BuiltinDocs.object___init___doc)
final void object___init__(PyObject[] args, String[] keywords) {
- // XXX: attempted fix for object(foo=1), etc
- // XXX: this doesn't work for metaclasses, for some reason
- /*
- if (args.length > 0) {
- throw Py.TypeError("default __new__ takes no parameters");
- }
- */
}
@ExposedGet(name = "__class__")
@@ -3974,10 +3990,15 @@
}
public PyTuple __getnewargs__() {
- //default is empty tuple
+ // default is empty tuple
return new PyTuple();
}
+ @ExposedClassMethod(doc = BuiltinDocs.object___subclasshook___doc)
+ public static PyObject object___subclasshook__(PyType type, PyObject subclass) {
+ return Py.NotImplemented;
+ }
+
/* arguments' conversion helpers */
public static class ConversionException extends Exception {
Modified: trunk/jython/src/org/python/core/PyType.java
===================================================================
--- trunk/jython/src/org/python/core/PyType.java 2011-03-18 01:26:55 UTC (rev 7244)
+++ trunk/jython/src/org/python/core/PyType.java 2011-03-18 02:25:16 UTC (rev 7245)
@@ -120,7 +120,7 @@
}
@ExposedNew
- public static PyObject type___new__(PyNewWrapper new_, boolean init, PyType subtype,
+ static final PyObject type___new__(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
// Special case: type(x) should return x.getType()
if (args.length == 1 && keywords.length == 0) {
@@ -150,6 +150,18 @@
return newType(new_, subtype, name, bases, dict);
}
+ @ExposedMethod(doc = BuiltinDocs.type___init___doc)
+ final void type___init__(PyObject[] args, String[] kwds) {
+ if (kwds.length > 0) {
+ throw Py.TypeError("type.__init__() takes no keyword arguments");
+ }
+
+ if (args.length != 1 && args.length != 3) {
+ throw Py.TypeError("type.__init__() takes 1 or 3 arguments");
+ }
+ object___init__(Py.EmptyObjects, Py.NoKeywords);
+ }
+
public static PyObject newType(PyNewWrapper new_, PyType metatype, String name, PyTuple bases,
PyObject dict) {
PyObject[] tmpBases = bases.getArray();
@@ -741,6 +753,10 @@
tp_flags = isBaseType ? tp_flags | Py.TPFLAGS_BASETYPE : tp_flags & ~Py.TPFLAGS_BASETYPE;
}
+ boolean isAbstract() {
+ return (tp_flags & Py.TPFLAGS_IS_ABSTRACT) != 0;
+ }
+
private void mro_internal() {
if (getType() == TYPE) {
mro = computeMro();
@@ -1684,6 +1700,26 @@
throw Py.TypeError(String.format("can't delete %s.__module__", name));
}
+ @ExposedGet(name = "__abstractmethods__")
+ public PyObject getAbstractmethods() {
+ PyObject result = dict.__finditem__("__abstractmethods__");
+ if (result == null) {
+ noAttributeError("__abstractmethods__");
+ }
+ return result;
+ }
+
+ @ExposedSet(name = "__abstractmethods__")
+ public void setAbstractmethods(PyObject value) {
+ // __abstractmethods__ should only be set once on a type, in abc.ABCMeta.__new__,
+ // so this function doesn't do anything special to update subclasses
+ dict.__setitem__("__abstractmethods__", value);
+ postSetattr("__abstractmethods__");
+ tp_flags = value.__nonzero__()
+ ? tp_flags | Py.TPFLAGS_IS_ABSTRACT
+ : tp_flags & ~Py.TPFLAGS_IS_ABSTRACT;
+ }
+
public int getNumSlots() {
return numSlots;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-18 01:27:02
|
Revision: 7244
http://jython.svn.sourceforge.net/jython/?rev=7244&view=rev
Author: pjenvey
Date: 2011-03-18 01:26:55 +0000 (Fri, 18 Mar 2011)
Log Message:
-----------
add ThreadState.enter/leaveRecursiveCall
Modified Paths:
--------------
trunk/jython/src/org/python/core/ThreadState.java
Modified: trunk/jython/src/org/python/core/ThreadState.java
===================================================================
--- trunk/jython/src/org/python/core/ThreadState.java 2011-03-17 23:02:35 UTC (rev 7243)
+++ trunk/jython/src/org/python/core/ThreadState.java 2011-03-18 01:26:55 UTC (rev 7244)
@@ -86,4 +86,14 @@
}
return compareStateDict;
}
+
+ public void enterRecursiveCall(String where) {
+ if (recursion_depth++ > systemState.getrecursionlimit()) {
+ throw Py.RuntimeError("maximum recursion depth exceeded" + where);
+ }
+ }
+
+ public void leaveRecursiveCall() {
+ --recursion_depth;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pj...@us...> - 2011-03-17 23:02:43
|
Revision: 7243
http://jython.svn.sourceforge.net/jython/?rev=7243&view=rev
Author: pjenvey
Date: 2011-03-17 23:02:35 +0000 (Thu, 17 Mar 2011)
Log Message:
-----------
might as well return the covariant type
Modified Paths:
--------------
trunk/jython/src/org/python/core/PyInstance.java
Modified: trunk/jython/src/org/python/core/PyInstance.java
===================================================================
--- trunk/jython/src/org/python/core/PyInstance.java 2011-03-17 22:18:37 UTC (rev 7242)
+++ trunk/jython/src/org/python/core/PyInstance.java 2011-03-17 23:02:35 UTC (rev 7243)
@@ -51,7 +51,7 @@
return new PyInstance(klass, dict);
}
- public PyObject fastGetClass() {
+ public PyClass fastGetClass() {
return instclass;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|