Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
7ade6485
Kaydet (Commit)
7ade6485
authored
Agu 26, 2007
tarafından
Eric Smith
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
PEP 3101: Completed string.Formatter class. Reimplemented field_name to object transformation.
üst
2bf4d5ba
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
237 additions
and
32 deletions
+237
-32
unicodeobject.h
Include/unicodeobject.h
+1
-2
string.py
Lib/string.py
+35
-7
test_string.py
Lib/test/test_string.py
+21
-2
test_unicode.py
Lib/test/test_unicode.py
+9
-0
string_format.h
Objects/stringlib/string_format.h
+0
-0
unicodeobject.c
Objects/unicodeobject.c
+157
-8
sysmodule.c
Python/sysmodule.c
+14
-13
No files found.
Include/unicodeobject.h
Dosyayı görüntüle @
7ade6485
...
...
@@ -1440,8 +1440,7 @@ PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strchr(
PyObject
*
_unicodeformatter_iterator
(
PyObject
*
str
);
PyObject
*
_unicodeformatter_lookup
(
PyObject
*
field_name
,
PyObject
*
args
,
PyObject
*
kwargs
);
_unicodeformatter_field_name_split
(
PyObject
*
field_name
);
#ifdef __cplusplus
}
...
...
Lib/string.py
Dosyayı görüntüle @
7ade6485
...
...
@@ -200,31 +200,59 @@ class Template(metaclass=_TemplateMetaclass):
# exposed here via the sys module. sys was chosen because it's always
# available and doesn't have to be dynamically loaded.
# The parser is implemented in sys._formatter_parser.
# The
"object lookup" is implemented in sys._formatter_lookup
# The
overall
parser is implemented in sys._formatter_parser.
# The
field name parser is implemented in sys._formatter_field_name_split
from
sys
import
_formatter_parser
,
_formatter_
lookup
from
sys
import
_formatter_parser
,
_formatter_
field_name_split
class
Formatter
:
def
format
(
self
,
format_string
,
*
args
,
**
kwargs
):
return
self
.
vformat
(
format_string
,
args
,
kwargs
)
def
vformat
(
self
,
format_string
,
args
,
kwargs
):
used_args
=
set
()
result
=
[]
for
(
is_markup
,
literal
,
field_name
,
format_spec
,
conversion
)
in
\
_formatter_parser
(
format_string
):
if
is_markup
:
# find the object
index
,
name
,
obj
=
_formatter_lookup
(
field_name
,
args
,
kwargs
)
# given the field_name, find the object it references
# split it into the first part, and and iterator that
# looks over the rest
first
,
rest
=
_formatter_field_name_split
(
field_name
)
used_args
.
add
(
first
)
obj
=
self
.
get_value
(
first
,
args
,
kwargs
)
# loop through the rest of the field_name, doing
# getattr or getitem as needed
for
is_attr
,
i
in
rest
:
if
is_attr
:
obj
=
getattr
(
obj
,
i
)
else
:
obj
=
obj
[
i
]
# do any conversion on the resulting object
if
conversion
==
'r'
:
obj
=
repr
(
obj
)
elif
conversion
==
's'
:
obj
=
str
(
obj
)
# format the object and append to the result
result
.
append
(
self
.
format_field
(
obj
,
format_spec
))
else
:
result
.
append
(
literal
)
self
.
check_unused_args
(
used_args
,
args
,
kwargs
)
return
''
.
join
(
result
)
def
get_value
(
self
,
key
,
args
,
kwargs
):
pass
if
isinstance
(
key
,
int
):
return
args
[
key
]
else
:
return
kwargs
[
key
]
def
check_unused_args
(
self
,
used_args
,
args
,
kwargs
):
pass
def
format_field
(
self
,
value
,
format_spec
):
pass
return
format
(
value
,
format_spec
)
Lib/test/test_string.py
Dosyayı görüntüle @
7ade6485
...
...
@@ -19,8 +19,27 @@ class ModuleTest(unittest.TestCase):
fmt
=
string
.
Formatter
()
self
.
assertEqual
(
fmt
.
format
(
"foo"
),
"foo"
)
# Formatter not working you for lookups
#self.assertEqual(fmt.format("foo{0}", "bar"), "foobar")
self
.
assertEqual
(
fmt
.
format
(
"foo{0}"
,
"bar"
),
"foobar"
)
self
.
assertEqual
(
fmt
.
format
(
"foo{1}{0}-{1}"
,
"bar"
,
6
),
"foo6bar-6"
)
self
.
assertEqual
(
fmt
.
format
(
"-{arg!r}-"
,
arg
=
'test'
),
"-'test'-"
)
class
NamespaceFormatter
(
string
.
Formatter
):
def
__init__
(
self
,
namespace
=
{}):
string
.
Formatter
.
__init__
(
self
)
self
.
namespace
=
namespace
def
get_value
(
self
,
key
,
args
,
kwds
):
if
isinstance
(
key
,
str
):
try
:
# Check explicitly passed arguments first
return
kwds
[
key
]
except
KeyError
:
return
self
.
namespace
[
key
]
else
:
string
.
Formatter
.
get_value
(
key
,
args
,
kwds
)
fmt
=
NamespaceFormatter
({
'greeting'
:
'hello'
})
self
.
assertEqual
(
fmt
.
format
(
"{greeting}, world!"
),
'hello, world!'
)
def
test_maketrans
(
self
):
...
...
Lib/test/test_unicode.py
Dosyayı görüntüle @
7ade6485
...
...
@@ -449,6 +449,10 @@ class UnicodeTest(
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
(
'{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'
)
...
...
@@ -539,7 +543,11 @@ class UnicodeTest(
self
.
assertRaises
(
ValueError
,
"}"
.
format
)
self
.
assertRaises
(
ValueError
,
"abc{0:{}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0.}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0[}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0]}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0.[]}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0..foo}"
.
format
,
0
)
self
.
assertRaises
(
ValueError
,
"{0[0}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{0[0:foo}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{c]}"
.
format
)
...
...
@@ -551,6 +559,7 @@ class UnicodeTest(
self
.
assertRaises
(
ValueError
,
"{0!rs}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{!}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{:}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{:s}"
.
format
)
self
.
assertRaises
(
ValueError
,
"{}"
.
format
)
# can't have a replacement on the field name portion
...
...
Objects/stringlib/string_format.h
Dosyayı görüntüle @
7ade6485
This diff is collapsed.
Click to expand it.
Objects/unicodeobject.c
Dosyayı görüntüle @
7ade6485
...
...
@@ -9161,9 +9161,8 @@ typedef struct {
static
void
formatteriter_dealloc
(
formatteriterobject
*
it
)
{
_PyObject_GC_UNTRACK
(
it
);
Py_XDECREF
(
it
->
str
);
PyObject_GC_Del
(
it
);
Py_XDECREF
(
it
->
str
);
PyObject_FREE
(
it
);
}
/* returns a tuple:
...
...
@@ -9313,7 +9312,7 @@ _unicodeformatter_iterator(PyObject *str)
{
formatteriterobject
*
it
;
it
=
PyObject_
GC_
New
(
formatteriterobject
,
&
PyFormatterIter_Type
);
it
=
PyObject_New
(
formatteriterobject
,
&
PyFormatterIter_Type
);
if
(
it
==
NULL
)
return
NULL
;
...
...
@@ -9326,17 +9325,167 @@ _unicodeformatter_iterator(PyObject *str)
PyUnicode_AS_UNICODE
(
str
),
PyUnicode_GET_SIZE
(
str
));
_PyObject_GC_TRACK
(
it
);
return
(
PyObject
*
)
it
;
}
PyObject
*
_unicodeformatter_lookup
(
PyObject
*
field_name
,
PyObject
*
args
,
PyObject
*
kwargs
)
/********************* FieldName Iterator ************************/
/* this is used to implement string.Formatter.vparse(). it parses
the field name into attribute and item values. */
typedef
struct
{
PyObject_HEAD
/* we know this to be a unicode object, but since we just keep
it around to keep the object alive, having it as PyObject
is okay */
PyObject
*
str
;
FieldNameIterator
it_field
;
}
fieldnameiterobject
;
static
void
fieldnameiter_dealloc
(
fieldnameiterobject
*
it
)
{
Py_XDECREF
(
it
->
str
);
PyObject_FREE
(
it
);
}
/* returns a tuple:
(is_attr, value)
is_attr is true if we used attribute syntax (e.g., '.foo')
false if we used index syntax (e.g., '[foo]')
value is an integer or string
*/
static
PyObject
*
fieldnameiter_next
(
fieldnameiterobject
*
it
)
{
int
result
;
int
is_attr
;
Py_ssize_t
idx
;
SubString
name
;
result
=
FieldNameIterator_next
(
&
it
->
it_field
,
&
is_attr
,
&
idx
,
&
name
);
if
(
result
==
0
||
result
==
1
)
{
/* if 0, error has already been set, if 1, iterator is empty */
return
NULL
;
}
else
{
PyObject
*
result
=
NULL
;
PyObject
*
is_attr_obj
=
NULL
;
PyObject
*
obj
=
NULL
;
is_attr_obj
=
PyBool_FromLong
(
is_attr
);
if
(
is_attr_obj
==
NULL
)
goto
error
;
/* either an integer or a string */
if
(
idx
!=
-
1
)
obj
=
PyInt_FromSsize_t
(
idx
);
else
obj
=
STRINGLIB_NEW
(
name
.
ptr
,
name
.
end
-
name
.
ptr
);
if
(
obj
==
NULL
)
goto
error
;
/* return a tuple of values */
result
=
PyTuple_Pack
(
2
,
is_attr_obj
,
obj
);
if
(
result
==
NULL
)
goto
error
;
return
result
;
error:
Py_XDECREF
(
result
);
Py_XDECREF
(
is_attr_obj
);
Py_XDECREF
(
obj
);
return
NULL
;
}
return
NULL
;
}
static
PyMethodDef
fieldnameiter_methods
[]
=
{
{
NULL
,
NULL
}
/* sentinel */
};
static
PyTypeObject
PyFieldNameIter_Type
=
{
PyVarObject_HEAD_INIT
(
&
PyType_Type
,
0
)
"fieldnameiterator"
,
/* tp_name */
sizeof
(
fieldnameiterobject
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
(
destructor
)
fieldnameiter_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
PyObject_GenericGetAttr
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
0
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
fieldnameiter_next
,
/* tp_iternext */
fieldnameiter_methods
,
/* tp_methods */
0
};
PyObject
*
_unicodeformatter_field_name_split
(
PyObject
*
field_name
)
{
SubString
first
;
Py_ssize_t
first_idx
;
fieldnameiterobject
*
it
;
PyObject
*
first_obj
=
NULL
;
PyObject
*
it_obj
=
NULL
;
PyObject
*
result
;
it
=
PyObject_New
(
fieldnameiterobject
,
&
PyFieldNameIter_Type
);
if
(
it
==
NULL
)
goto
error
;
it
->
str
=
NULL
;
it_obj
=
(
PyObject
*
)
it
;
if
(
!
field_name_split
(
STRINGLIB_STR
(
field_name
),
STRINGLIB_LEN
(
field_name
),
&
first
,
&
first_idx
,
&
it
->
it_field
))
goto
error
;
/* first becomes an integer, if possible, else a string */
if
(
first_idx
!=
-
1
)
first_obj
=
PyInt_FromSsize_t
(
first_idx
);
else
/* convert "first" into a string object */
first_obj
=
STRINGLIB_NEW
(
first
.
ptr
,
first
.
end
-
first
.
ptr
);
if
(
first_obj
==
NULL
)
goto
error
;
/* take ownership, give the object to the iterator. this is
just to keep the field_name alive */
Py_INCREF
(
field_name
);
it
->
str
=
field_name
;
/* return a tuple of values */
result
=
PyTuple_Pack
(
2
,
first_obj
,
it_obj
);
if
(
result
==
NULL
)
goto
error
;
return
result
;
error:
Py_XDECREF
(
it_obj
);
Py_XDECREF
(
first_obj
);
return
NULL
;
}
/********************* Unicode Iterator **************************/
...
...
Python/sysmodule.c
Dosyayı görüntüle @
7ade6485
...
...
@@ -683,28 +683,28 @@ sys_formatter_iterator(PyObject *self, PyObject *args)
return
_unicodeformatter_iterator
(
str
);
}
/* sys_formatter_lookup is used to implement string.Formatter.vformat.
it takes an PEP 3101 "field name", args, and kwargs, and returns a
tuple (index, name, object). see unicodeobject.c's
_unicodeformatter_lookup for details */
/* sys_formatter_field_name_split is used to implement
string.Formatter.vformat. it takes an PEP 3101 "field name", and
returns a tuple of (first, rest): "first", the part before the
first '.' or '['; and "rest", an iterator for the rest of the field
name. see unicodeobjects' _unicode_formatter_field_name_split for
details */
static
PyObject
*
sys_formatter_
lookup
(
PyObject
*
self
,
PyObject
*
args
)
sys_formatter_
field_name_split
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
field_name
;
PyObject
*
arg_args
;
PyObject
*
kwargs
;
if
(
!
PyArg_ParseTuple
(
args
,
"O
OO:_formatter_lookup"
,
&
field_name
,
&
arg_args
,
&
kwargs
))
if
(
!
PyArg_ParseTuple
(
args
,
"O
:_formatter_field_name_split"
,
&
field_name
))
return
NULL
;
if
(
!
PyUnicode_Check
(
field_name
))
{
PyErr_SetString
(
PyExc_TypeError
,
"
_formatter_lookup
expects unicode object"
);
PyErr_SetString
(
PyExc_TypeError
,
"_formatter_field_name_split "
"expects unicode object"
);
return
NULL
;
}
return
_unicodeformatter_
lookup
(
field_name
,
arg_args
,
kwargs
);
return
_unicodeformatter_
field_name_split
(
field_name
);
}
...
...
@@ -773,7 +773,8 @@ static PyMethodDef sys_methods[] = {
{
"_current_frames"
,
sys_current_frames
,
METH_NOARGS
,
current_frames_doc
},
{
"_formatter_parser"
,
sys_formatter_iterator
,
METH_VARARGS
},
{
"_formatter_lookup"
,
sys_formatter_lookup
,
METH_VARARGS
},
{
"_formatter_field_name_split"
,
sys_formatter_field_name_split
,
METH_VARARGS
},
{
"displayhook"
,
sys_displayhook
,
METH_O
,
displayhook_doc
},
{
"exc_info"
,
sys_exc_info
,
METH_NOARGS
,
exc_info_doc
},
{
"excepthook"
,
sys_excepthook
,
METH_VARARGS
,
excepthook_doc
},
...
...
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