Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
e039ff0f
Commit
e039ff0f
authored
Sep 20, 2015
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #925 from undingen/lxml3
Misc small fixes for lxml
parents
4cc0a340
f90202c8
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
175 additions
and
82 deletions
+175
-82
src/analysis/type_analysis.cpp
src/analysis/type_analysis.cpp
+5
-1
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+3
-1
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+1
-1
src/capi/typeobject.h
src/capi/typeobject.h
+1
-0
src/core/types.h
src/core/types.h
+1
-1
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+17
-22
src/runtime/capi.cpp
src/runtime/capi.cpp
+9
-15
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+22
-0
src/runtime/dict.cpp
src/runtime/dict.cpp
+15
-12
src/runtime/import.cpp
src/runtime/import.cpp
+9
-6
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+26
-4
src/runtime/types.cpp
src/runtime/types.cpp
+52
-15
src/runtime/util.cpp
src/runtime/util.cpp
+12
-3
src/runtime/util.h
src/runtime/util.h
+1
-1
test/tests/unicode_test.py
test/tests/unicode_test.py
+1
-0
No files found.
src/analysis/type_analysis.cpp
View file @
e039ff0f
...
...
@@ -418,9 +418,13 @@ private:
}
void
*
visit_name
(
AST_Name
*
node
)
override
{
auto
name_scope
=
scope_info
->
getScopeTypeOfName
(
node
->
id
);
if
(
node
->
lookup_type
==
ScopeInfo
::
VarScopeType
::
UNKNOWN
)
node
->
lookup_type
=
scope_info
->
getScopeTypeOfName
(
node
->
id
);
auto
name_scope
=
node
->
lookup_type
;
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
GLOBAL
)
{
if
(
node
->
id
.
s
()
==
"None"
)
return
NONE
;
return
UNKNOWN
;
}
...
...
src/asm_writing/rewriter.cpp
View file @
e039ff0f
...
...
@@ -1693,7 +1693,7 @@ assembler::Register Rewriter::allocReg(Location dest, Location otherThan) {
// Spill the register whose next use is farthest in the future
assert
(
found
);
spillRegister
(
best_reg
,
/* preserve */
otherThan
);
assert
(
vars_by_location
.
count
(
best_reg
)
==
0
);
assert
(
failed
||
vars_by_location
.
count
(
best_reg
)
==
0
);
return
best_reg
;
}
else
if
(
dest
.
type
==
Location
::
Register
)
{
assembler
::
Register
reg
(
dest
.
regnum
);
...
...
@@ -1736,6 +1736,8 @@ assembler::XMMRegister Rewriter::allocXMMReg(Location dest, Location otherThan)
}
void
Rewriter
::
addLocationToVar
(
RewriterVar
*
var
,
Location
l
)
{
if
(
failed
)
return
;
assert
(
!
var
->
isInLocation
(
l
));
assert
(
vars_by_location
.
count
(
l
)
==
0
);
...
...
src/capi/typeobject.cpp
View file @
e039ff0f
...
...
@@ -1316,7 +1316,7 @@ static int method_is_overloaded(PyObject* left, PyObject* right, const char* nam
SLOT1
(
slot_mp_subscript
,
"__getitem__"
,
PyObject
*
,
"O"
)
static
int
slot_mp_ass_subscript
(
PyObject
*
self
,
PyObject
*
key
,
PyObject
*
value
)
noexcept
{
int
slot_mp_ass_subscript
(
PyObject
*
self
,
PyObject
*
key
,
PyObject
*
value
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_slot_mpasssubscript"
,
SLOT_AVOIDABILITY
(
self
));
PyObject
*
res
;
...
...
src/capi/typeobject.h
View file @
e039ff0f
...
...
@@ -47,6 +47,7 @@ PyObject* slot_tp_iter(PyObject* self) noexcept;
PyObject
*
slot_tp_iternext
(
PyObject
*
self
)
noexcept
;
PyObject
*
slot_tp_new
(
PyTypeObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
noexcept
;
PyObject
*
slot_mp_subscript
(
PyObject
*
self
,
PyObject
*
arg1
)
noexcept
;
int
slot_mp_ass_subscript
(
PyObject
*
self
,
PyObject
*
key
,
PyObject
*
value
)
noexcept
;
int
slot_sq_contains
(
PyObject
*
self
,
PyObject
*
value
)
noexcept
;
Py_ssize_t
slot_sq_length
(
PyObject
*
self
)
noexcept
;
PyObject
*
slot_tp_getattr_hook
(
PyObject
*
self
,
PyObject
*
name
)
noexcept
;
...
...
src/core/types.h
View file @
e039ff0f
...
...
@@ -482,7 +482,7 @@ inline BoxedString* internStringMortal(llvm::StringRef s) {
}
// TODO this is an immortal intern for now
inline
void
internStringMortalInplace
(
BoxedString
*&
s
)
{
inline
void
internStringMortalInplace
(
BoxedString
*&
s
)
noexcept
{
PyString_InternInPlace
((
PyObject
**
)
&
s
);
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
e039ff0f
...
...
@@ -464,7 +464,7 @@ Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) {
// Well, it gets passed to PyImport_ImportModuleLevel() and then import_module_level(),
// which ignores it. So we don't even pass it through.
name
=
coerceUnicodeToStr
(
name
);
name
=
coerceUnicodeToStr
<
CXX
>
(
name
);
if
(
name
->
cls
!=
str_cls
)
{
raiseExcHelper
(
TypeError
,
"__import__() argument 1 must be string, not %s"
,
getTypeName
(
name
));
...
...
@@ -479,7 +479,7 @@ Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) {
}
Box
*
delattrFunc
(
Box
*
obj
,
Box
*
_str
)
{
_str
=
coerceUnicodeToStr
(
_str
);
_str
=
coerceUnicodeToStr
<
CXX
>
(
_str
);
if
(
_str
->
cls
!=
str_cls
)
raiseExcHelper
(
TypeError
,
"attribute name must be string, not '%s'"
,
getTypeName
(
_str
));
...
...
@@ -543,15 +543,9 @@ Box* getattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
}
}
try
{
_str
=
coerceUnicodeToStr
(
_str
);
}
catch
(
ExcInfo
e
)
{
if
(
S
==
CAPI
)
{
setCAPIException
(
e
);
return
NULL
;
}
else
throw
e
;
}
_str
=
coerceUnicodeToStr
<
S
>
(
_str
);
if
(
S
==
CAPI
&&
!
_str
)
return
NULL
;
if
(
!
PyString_Check
(
_str
))
{
if
(
S
==
CAPI
)
{
...
...
@@ -601,7 +595,7 @@ Box* getattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
}
Box
*
setattrFunc
(
Box
*
obj
,
Box
*
_str
,
Box
*
value
)
{
_str
=
coerceUnicodeToStr
(
_str
);
_str
=
coerceUnicodeToStr
<
CXX
>
(
_str
);
if
(
_str
->
cls
!=
str_cls
)
{
raiseExcHelper
(
TypeError
,
"setattr(): attribute name must be string"
);
...
...
@@ -647,19 +641,20 @@ Box* hasattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
// value is fixed.
if
(
!
PyString_CheckExact
(
_str
)
&&
!
PyUnicode_CheckExact
(
_str
))
rewrite_args
=
NULL
;
else
else
{
if
(
PyString_CheckExact
(
_str
)
&&
PyString_CHECK_INTERNED
(
_str
)
==
SSTATE_INTERNED_IMMORTAL
)
{
// can avoid keeping the extra gc reference
}
else
{
rewrite_args
->
rewriter
->
addGCReference
(
_str
);
}
rewrite_args
->
arg2
->
addGuard
((
intptr_t
)
arg2
);
}
}
try
{
_str
=
coerceUnicodeToStr
(
_str
);
}
catch
(
ExcInfo
e
)
{
if
(
S
==
CAPI
)
{
setCAPIException
(
e
);
return
NULL
;
}
else
throw
e
;
}
_str
=
coerceUnicodeToStr
<
S
>
(
_str
);
if
(
S
==
CAPI
&&
!
_str
)
return
NULL
;
if
(
!
PyString_Check
(
_str
))
{
if
(
S
==
CAPI
)
{
...
...
src/runtime/capi.cpp
View file @
e039ff0f
...
...
@@ -56,7 +56,7 @@ BoxedClass* capifunc_cls;
}
extern
"C"
void
_PyErr_BadInternalCall
(
const
char
*
filename
,
int
lineno
)
noexcept
{
Py
_FatalError
(
"unimplemented"
);
Py
Err_Format
(
PyExc_SystemError
,
"%s:%d: bad argument to internal function"
,
filename
,
lineno
);
}
extern
"C"
PyObject
*
PyObject_Format
(
PyObject
*
obj
,
PyObject
*
format_spec
)
noexcept
{
...
...
@@ -1033,20 +1033,6 @@ extern "C" int PyErr_WarnEx(PyObject* category, const char* text, Py_ssize_t sta
return
-
1
;
}
extern
"C"
PyObject
*
PyImport_Import
(
PyObject
*
module_name
)
noexcept
{
RELEASE_ASSERT
(
module_name
,
""
);
RELEASE_ASSERT
(
module_name
->
cls
==
str_cls
,
""
);
try
{
std
::
string
_module_name
=
static_cast
<
BoxedString
*>
(
module_name
)
->
s
();
return
importModuleLevel
(
_module_name
,
None
,
None
,
-
1
);
}
catch
(
ExcInfo
e
)
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
}
extern
"C"
void
*
PyObject_Malloc
(
size_t
sz
)
noexcept
{
return
gc_compat_malloc
(
sz
);
}
...
...
@@ -1388,6 +1374,14 @@ extern "C" PyObject* PyCFunction_GetSelf(PyObject* op) noexcept {
return
static_cast
<
BoxedCApiFunction
*>
(
op
)
->
passthrough
;
}
extern
"C"
int
PyCFunction_GetFlags
(
PyObject
*
op
)
noexcept
{
if
(
!
PyCFunction_Check
(
op
))
{
PyErr_BadInternalCall
();
return
-
1
;
}
return
static_cast
<
BoxedCApiFunction
*>
(
op
)
->
method_def
->
ml_flags
;
}
extern
"C"
int
_PyEval_SliceIndex
(
PyObject
*
v
,
Py_ssize_t
*
pi
)
noexcept
{
if
(
v
!=
NULL
)
{
Py_ssize_t
x
;
...
...
src/runtime/classobj.cpp
View file @
e039ff0f
...
...
@@ -267,6 +267,27 @@ Box* classobjStr(Box* _obj) {
return
boxStringTwine
(
llvm
::
Twine
(
static_cast
<
BoxedString
*>
(
_mod
)
->
s
())
+
"."
+
cls
->
name
->
s
());
}
Box
*
classobjRepr
(
Box
*
_obj
)
{
if
(
!
isSubclass
(
_obj
->
cls
,
classobj_cls
))
{
raiseExcHelper
(
TypeError
,
"descriptor '__repr__' requires a 'classobj' object but received an '%s'"
,
getTypeName
(
_obj
));
}
BoxedClassobj
*
cls
=
static_cast
<
BoxedClassobj
*>
(
_obj
);
static
BoxedString
*
module_str
=
internStringImmortal
(
"__module__"
);
Box
*
mod
=
cls
->
getattr
(
module_str
);
const
char
*
name
;
if
(
cls
->
name
==
NULL
||
!
PyString_Check
(
cls
->
name
))
name
=
"?"
;
else
name
=
PyString_AsString
(
cls
->
name
);
if
(
mod
==
NULL
||
!
PyString_Check
(
mod
))
return
PyString_FromFormat
(
"<class ?.%s at %p>"
,
name
,
cls
);
else
return
PyString_FromFormat
(
"<class %s.%s at %p>"
,
PyString_AsString
(
mod
),
name
,
cls
);
}
// Analogous to CPython's instance_getattr2
static
Box
*
instanceGetattributeSimple
(
BoxedInstance
*
inst
,
BoxedString
*
attr_str
,
...
...
@@ -1512,6 +1533,7 @@ void setupClassobj() {
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classobjGetattribute
,
UNKNOWN
,
2
)));
classobj_cls
->
giveAttr
(
"__setattr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classobjSetattr
,
UNKNOWN
,
3
)));
classobj_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classobjStr
,
STR
,
1
)));
classobj_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classobjRepr
,
STR
,
1
)));
classobj_cls
->
giveAttr
(
"__dict__"
,
dict_descr
);
classobj_cls
->
freeze
();
...
...
src/runtime/dict.cpp
View file @
e039ff0f
...
...
@@ -322,18 +322,20 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
return
d
->
getOrNull
(
key
);
}
// XXX this would be easy to make much faster.
// This path doesn't exist in CPython; we have it to support extension modules that do
// something along the lines of PyDict_GetItem(PyModule_GetDict()):
try
{
return
getitem
(
dict
,
key
);
}
catch
(
ExcInfo
e
)
{
// PyDict_GetItem has special error behavior in CPython for backwards-compatibility reasons,
// and apparently it's important enough that we have to follow that.
// The behavior is that all errors get suppressed, and in fact I think it's supposed to
// restore the previous exception afterwards (we don't do that yet).
return
NULL
;
auto
&&
tstate
=
_PyThreadState_Current
;
if
(
tstate
!=
NULL
&&
tstate
->
curexc_type
!=
NULL
)
{
/* preserve the existing exception */
PyObject
*
err_type
,
*
err_value
,
*
err_tb
;
PyErr_Fetch
(
&
err_type
,
&
err_value
,
&
err_tb
);
Box
*
b
=
getitemInternal
<
CAPI
>
(
dict
,
key
,
NULL
);
/* ignore errors */
PyErr_Restore
(
err_type
,
err_value
,
err_tb
);
return
b
;
}
else
{
Box
*
b
=
getitemInternal
<
CAPI
>
(
dict
,
key
,
NULL
);
if
(
b
==
NULL
)
PyErr_Clear
();
return
b
;
}
}
...
...
@@ -430,6 +432,7 @@ static int dict_ass_sub(PyDictObject* mp, PyObject* v, PyObject* w) noexcept {
assert
(
res
==
None
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
return
0
;
}
...
...
src/runtime/import.cpp
View file @
e039ff0f
...
...
@@ -594,22 +594,25 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
}
}
extern
"C"
PyObject
*
PyImport_Import
Module
(
const
char
*
name
)
noexcept
{
if
(
strcmp
(
"__builtin__"
,
name
)
==
0
)
return
builtins_module
;
extern
"C"
PyObject
*
PyImport_Import
(
PyObject
*
module_
name
)
noexcept
{
RELEASE_ASSERT
(
module_name
,
""
);
RELEASE_ASSERT
(
module_name
->
cls
==
str_cls
,
""
)
;
try
{
// TODO: check if this has the same behaviour as the cpython implementation
std
::
string
str
=
name
;
BoxedList
*
silly_list
=
new
BoxedList
();
listAppendInternal
(
silly_list
,
boxString
(
"__doc__"
));
return
import
(
0
,
silly_list
,
str
);
return
import
(
0
,
silly_list
,
((
BoxedString
*
)
module_name
)
->
s
()
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
extern
"C"
PyObject
*
PyImport_ImportModule
(
const
char
*
name
)
noexcept
{
return
PyImport_Import
(
boxString
(
name
));
}
/* Get the module object corresponding to a module name.
First check the modules dictionary if there's one there,
if not, create a new one and insert it in the modules dictionary.
...
...
@@ -683,7 +686,7 @@ extern "C" Box* import(int level, Box* from_imports, llvm::StringRef module_name
}
Box
*
impFindModule
(
Box
*
_name
,
BoxedList
*
path
)
{
_name
=
coerceUnicodeToStr
(
_name
);
_name
=
coerceUnicodeToStr
<
CXX
>
(
_name
);
RELEASE_ASSERT
(
_name
->
cls
==
str_cls
,
""
);
BoxedString
*
name
=
static_cast
<
BoxedString
*>
(
_name
);
...
...
src/runtime/objmodel.cpp
View file @
e039ff0f
...
...
@@ -3488,7 +3488,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
}
for
(
const
auto
&
p
:
*
d_kwargs
)
{
auto
k
=
coerceUnicodeToStr
(
p
.
first
);
auto
k
=
coerceUnicodeToStr
<
CXX
>
(
p
.
first
);
if
(
k
->
cls
!=
str_cls
)
raiseExcHelper
(
TypeError
,
"%s() keywords must be strings"
,
func_name
);
...
...
@@ -4720,7 +4720,6 @@ static Box* callItemAttr(Box* target, BoxedString* item_str, Box* item, Box* val
template
<
ExceptionStyle
S
>
static
Box
*
callItemOrSliceAttr
(
Box
*
target
,
BoxedString
*
item_str
,
BoxedString
*
slice_str
,
Box
*
slice
,
Box
*
value
,
CallRewriteArgs
*
rewrite_args
)
noexcept
(
S
==
CAPI
)
{
// This function contains a lot of logic for deciding between whether to call
// the slice operator or the item operator, so we can match CPython's behavior
// on custom classes that define those operators. However, for builtin types,
...
...
@@ -4979,6 +4978,12 @@ extern "C" Box* getitem_capi(Box* target, Box* slice) noexcept {
return
rtn
;
}
static
void
setitemHelper
(
Box
*
target
,
Box
*
slice
,
Box
*
value
)
{
int
ret
=
target
->
cls
->
tp_as_mapping
->
mp_ass_subscript
(
target
,
slice
,
value
);
if
(
ret
==
-
1
)
throwCAPIException
();
}
// target[slice] = value
extern
"C"
void
setitem
(
Box
*
target
,
Box
*
slice
,
Box
*
value
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_setitem"
,
10
);
...
...
@@ -4992,6 +4997,23 @@ extern "C" void setitem(Box* target, Box* slice, Box* value) {
static
BoxedString
*
setitem_str
=
internStringImmortal
(
"__setitem__"
);
static
BoxedString
*
setslice_str
=
internStringImmortal
(
"__setslice__"
);
auto
&&
m
=
target
->
cls
->
tp_as_mapping
;
if
(
m
&&
m
->
mp_ass_subscript
&&
m
->
mp_ass_subscript
!=
slot_mp_ass_subscript
)
{
if
(
rewriter
.
get
())
{
RewriterVar
*
r_obj
=
rewriter
->
getArg
(
0
);
RewriterVar
*
r_slice
=
rewriter
->
getArg
(
1
);
RewriterVar
*
r_value
=
rewriter
->
getArg
(
2
);
RewriterVar
*
r_cls
=
r_obj
->
getAttr
(
offsetof
(
Box
,
cls
));
RewriterVar
*
r_m
=
r_cls
->
getAttr
(
offsetof
(
BoxedClass
,
tp_as_mapping
));
r_m
->
addGuardNotEq
(
0
);
rewriter
->
call
(
true
,
(
void
*
)
setitemHelper
,
r_obj
,
r_slice
,
r_value
);
rewriter
->
commit
();
}
setitemHelper
(
target
,
slice
,
value
);
return
;
}
Box
*
rtn
;
if
(
rewriter
.
get
())
{
CallRewriteArgs
rewrite_args
(
rewriter
.
get
(),
rewriter
->
getArg
(
0
),
rewriter
->
getReturnDestination
());
...
...
@@ -5502,7 +5524,7 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
}
for
(
const
auto
&
p
:
*
attr_dict
)
{
auto
k
=
coerceUnicodeToStr
(
p
.
first
);
auto
k
=
coerceUnicodeToStr
<
CXX
>
(
p
.
first
);
RELEASE_ASSERT
(
k
->
cls
==
str_cls
,
""
);
BoxedString
*
s
=
static_cast
<
BoxedString
*>
(
k
);
...
...
@@ -5831,7 +5853,7 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) {
}
idx
++
;
attr_name
=
coerceUnicodeToStr
(
attr_name
);
attr_name
=
coerceUnicodeToStr
<
CXX
>
(
attr_name
);
if
(
attr_name
->
cls
!=
str_cls
)
raiseExcHelper
(
TypeError
,
"attribute name must be string, not '%s'"
,
getTypeName
(
attr_name
));
...
...
src/runtime/types.cpp
View file @
e039ff0f
...
...
@@ -813,7 +813,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
ParamReceiveSpec
paramspec
(
4
,
3
,
false
,
false
);
bool
rewrite_success
=
false
;
static
ParamNames
param_names
({
"string"
,
"encoding"
,
"errors"
},
""
,
""
);
static
ParamNames
param_names
({
"
"
,
"
string"
,
"encoding"
,
"errors"
},
""
,
""
);
static
Box
*
defaults
[
3
]
=
{
NULL
,
NULL
,
NULL
};
Box
*
oargs
[
1
];
...
...
@@ -2246,7 +2246,7 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2256,11 +2256,27 @@ public:
return
None
;
}
static
int
ass_sub
(
PyDictObject
*
mp
,
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
try
{
Box
*
res
;
if
(
w
==
NULL
)
{
res
=
AttrWrapper
::
delitem
((
Box
*
)
mp
,
v
);
}
else
{
res
=
AttrWrapper
::
setitem
((
Box
*
)
mp
,
v
,
w
);
}
assert
(
res
==
None
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
return
0
;
}
static
Box
*
setdefault
(
Box
*
_self
,
Box
*
_key
,
Box
*
value
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2277,7 +2293,7 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2289,19 +2305,25 @@ public:
return
r
;
}
static
Box
*
getitem
(
Box
*
_self
,
Box
*
_key
)
{
template
<
ExceptionStyle
S
>
static
Box
*
getitem
(
Box
*
_self
,
Box
*
_key
)
noexcept
(
S
==
CAPI
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
S
>
(
_key
);
if
(
S
==
CAPI
&&
!
_key
)
return
NULL
;
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"%s"
,
_key
->
cls
->
tp_name
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
internStringMortalInplace
(
key
);
Box
*
r
=
self
->
b
->
getattr
(
key
);
if
(
!
r
)
raiseExcHelper
(
KeyError
,
"'%s'"
,
key
->
data
());
if
(
!
r
)
{
if
(
S
==
CXX
)
raiseExcHelper
(
KeyError
,
"'%s'"
,
key
->
data
());
else
PyErr_Format
(
KeyError
,
"'%s'"
,
key
->
data
());
}
return
r
;
}
...
...
@@ -2309,7 +2331,7 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2330,7 +2352,7 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"%s"
,
_key
->
cls
->
tp_name
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2367,11 +2389,13 @@ public:
return
boxString
(
os
.
str
());
}
static
Box
*
contains
(
Box
*
_self
,
Box
*
_key
)
{
template
<
ExceptionStyle
S
>
static
Box
*
contains
(
Box
*
_self
,
Box
*
_key
)
noexcept
(
S
==
CAPI
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
(
_key
);
_key
=
coerceUnicodeToStr
<
S
>
(
_key
);
if
(
S
==
CAPI
&&
!
_key
)
return
NULL
;
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
...
...
@@ -2381,6 +2405,13 @@ public:
return
r
?
True
:
False
;
}
static
int
sq_contains
(
Box
*
_self
,
Box
*
_key
)
noexcept
{
Box
*
rtn
=
contains
<
CAPI
>
(
_self
,
_key
);
if
(
!
rtn
)
return
-
1
;
return
rtn
==
True
;
}
static
Box
*
keys
(
Box
*
_self
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -2702,7 +2733,7 @@ Box* objectHash(Box* obj) {
}
Box
*
objectSetattr
(
Box
*
obj
,
Box
*
attr
,
Box
*
value
)
{
attr
=
coerceUnicodeToStr
(
attr
);
attr
=
coerceUnicodeToStr
<
CXX
>
(
attr
);
if
(
attr
->
cls
!=
str_cls
)
{
raiseExcHelper
(
TypeError
,
"attribute name must be string, not '%s'"
,
attr
->
cls
->
tp_name
);
}
...
...
@@ -3839,10 +3870,13 @@ void setupRuntime() {
static
PyMappingMethods
attrwrapper_as_mapping
;
attrwrapper_cls
->
tp_as_mapping
=
&
attrwrapper_as_mapping
;
static
PySequenceMethods
attrwrapper_as_sequence
;
attrwrapper_cls
->
tp_as_sequence
=
&
attrwrapper_as_sequence
;
attrwrapper_cls
->
giveAttr
(
"__setitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
setitem
,
UNKNOWN
,
3
)));
attrwrapper_cls
->
giveAttr
(
"pop"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
pop
,
UNKNOWN
,
3
,
false
,
false
),
{
NULL
}));
attrwrapper_cls
->
giveAttr
(
"__getitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
getitem
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__getitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
getitem
<
CXX
>
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__delitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
delitem
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"setdefault"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
setdefault
,
UNKNOWN
,
3
)));
...
...
@@ -3850,7 +3884,7 @@ void setupRuntime() {
"get"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
get
,
UNKNOWN
,
3
,
false
,
false
),
{
None
}));
attrwrapper_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
str
,
UNKNOWN
,
1
)));
attrwrapper_cls
->
giveAttr
(
"__contains__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
contains
,
UNKNOWN
,
2
)));
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
contains
<
CXX
>
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__eq__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
eq
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__ne__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
ne
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"keys"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
keys
,
LIST
,
1
)));
...
...
@@ -3868,6 +3902,9 @@ void setupRuntime() {
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
update
,
NONE
,
1
,
true
,
true
)));
attrwrapper_cls
->
freeze
();
attrwrapper_cls
->
tp_iter
=
AttrWrapper
::
iter
;
attrwrapper_cls
->
tp_as_mapping
->
mp_subscript
=
(
binaryfunc
)
AttrWrapper
::
getitem
<
CAPI
>
;
attrwrapper_cls
->
tp_as_mapping
->
mp_ass_subscript
=
(
objobjargproc
)
AttrWrapper
::
ass_sub
;
attrwrapper_cls
->
tp_as_sequence
->
sq_contains
=
(
objobjproc
)
AttrWrapper
::
sq_contains
;
attrwrapperiter_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapperIter
::
hasnext
,
UNKNOWN
,
1
)));
...
...
src/runtime/util.cpp
View file @
e039ff0f
...
...
@@ -104,19 +104,28 @@ Box* noneIfNull(Box* b) {
}
}
Box
*
coerceUnicodeToStr
(
Box
*
unicode
)
{
template
<
ExceptionStyle
S
>
Box
*
coerceUnicodeToStr
(
Box
*
unicode
)
noexcept
(
S
==
CAPI
)
{
if
(
!
isSubclass
(
unicode
->
cls
,
unicode_cls
))
return
unicode
;
Box
*
r
=
PyUnicode_AsASCIIString
(
unicode
);
if
(
!
r
)
{
PyErr_Clear
();
raiseExcHelper
(
TypeError
,
"Cannot use non-ascii unicode strings as attribute names or keywords"
);
if
(
S
==
CAPI
)
{
PyErr_SetString
(
TypeError
,
"Cannot use non-ascii unicode strings as attribute names or keywords"
);
return
NULL
;
}
else
{
PyErr_Clear
();
raiseExcHelper
(
TypeError
,
"Cannot use non-ascii unicode strings as attribute names or keywords"
);
}
}
return
r
;
}
// force instantiation:
template
Box
*
coerceUnicodeToStr
<
CXX
>(
Box
*
unicode
);
template
Box
*
coerceUnicodeToStr
<
CAPI
>(
Box
*
unicode
);
Box
*
boxStringFromCharPtr
(
const
char
*
s
)
{
return
boxString
(
s
);
}
...
...
src/runtime/util.h
View file @
e039ff0f
...
...
@@ -56,7 +56,7 @@ Box* boxStringFromCharPtr(const char* s);
// strings and a string that happens to be its encoding. It seems safer to just encode as ascii,
// which will throw an exception if you try to pass something that might run into this risk.
// (We wrap the unicode error and throw a TypeError)
Box
*
coerceUnicodeToStr
(
Box
*
unicode
);
template
<
ExceptionStyle
S
>
Box
*
coerceUnicodeToStr
(
Box
*
unicode
)
noexcept
(
S
==
CAPI
);
extern
"C"
bool
hasnext
(
Box
*
o
);
extern
"C"
void
dump
(
void
*
p
);
...
...
test/tests/unicode_test.py
View file @
e039ff0f
...
...
@@ -165,3 +165,4 @@ class C(object):
return
MyUnicode
(
"hello world"
)
print
type
(
unicode
(
C
()))
print
unicode
(
"test"
,
encoding
=
"UTF-8"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment