merge from trunk

This commit is contained in:
Benjamin Peterson
2008-10-11 00:49:57 +00:00
parent 2d8dcdcb06
commit f10a79aad4
40 changed files with 621 additions and 305 deletions

View File

@@ -111,7 +111,7 @@ dist:
# archive the HTML
make html
cp -a build/html dist/python$(DISTVERSION)-docs-html
cp -pPR build/html dist/python$(DISTVERSION)-docs-html
tar -C dist -cf dist/python$(DISTVERSION)-docs-html.tar python$(DISTVERSION)-docs-html
bzip2 -9 -k dist/python$(DISTVERSION)-docs-html.tar
(cd dist; zip -q -r -9 python$(DISTVERSION)-docs-html.zip python$(DISTVERSION)-docs-html)
@@ -120,7 +120,7 @@ dist:
# archive the text build
make text
cp -a build/text dist/python$(DISTVERSION)-docs-text
cp -pPR build/text dist/python$(DISTVERSION)-docs-text
tar -C dist -cf dist/python$(DISTVERSION)-docs-text.tar python$(DISTVERSION)-docs-text
bzip2 -9 -k dist/python$(DISTVERSION)-docs-text.tar
(cd dist; zip -q -r -9 python$(DISTVERSION)-docs-text.zip python$(DISTVERSION)-docs-text)

View File

@@ -744,11 +744,11 @@ created.
:cmacro:`Py_END_ALLOW_THREADS` macros is acceptable.
The return value is an opaque "handle" to the thread state when
:cfunc:`PyGILState_Acquire` was called, and must be passed to
:cfunc:`PyGILState_Ensure` was called, and must be passed to
:cfunc:`PyGILState_Release` to ensure Python is left in the same state. Even
though recursive calls are allowed, these handles *cannot* be shared - each
unique call to :cfunc:`PyGILState_Ensure` must save the handle for its call to
:cfunc:`PyGILState_Release`.
unique call to :cfunc:`PyGILState_Ensure` must save the handle for its call
to :cfunc:`PyGILState_Release`.
When the function returns, the current thread will hold the GIL. Failure is a
fatal error.

View File

@@ -41,13 +41,6 @@ today_fmt = '%B %d, %Y'
# List of files that shouldn't be included in the build.
unused_docs = [
'whatsnew/2.0',
'whatsnew/2.1',
'whatsnew/2.2',
'whatsnew/2.3',
'whatsnew/2.4',
'whatsnew/2.5',
'whatsnew/2.6',
'maclib/scrap',
'library/xmllib',
'library/xml.etree',

View File

@@ -4,7 +4,7 @@
.. toctree::
whatsnew/3.0.rst
whatsnew/index.rst
tutorial/index.rst
using/index.rst
reference/index.rst

View File

@@ -299,7 +299,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
.. method:: FTP.quit()
Send a ``QUIT`` command to the server and close the connection. This is the
"polite" way to close a connection, but it may raise an exception of the server
"polite" way to close a connection, but it may raise an exception if the server
responds with an error to the ``QUIT`` command. This implies a call to the
:meth:`close` method which renders the :class:`FTP` instance useless for
subsequent calls (see below).

View File

@@ -22,9 +22,8 @@ are always available. They are listed here in alphabetical order.
The function is invoked by the :keyword:`import` statement. It mainly exists
so that you can replace it with another function that has a compatible
interface, in order to change the semantics of the :keyword:`import`
statement. See also the built-in module :mod:`imp`, which
defines some useful operations out of which you can build your own
:func:`__import__` function.
statement. See the built-in module :mod:`imp`, which defines some useful
operations out of which you can build your own :func:`__import__` function.
For example, the statement ``import spam`` results in the following call:
``__import__('spam', globals(), locals(), [], -1)``; the statement
@@ -1201,6 +1200,18 @@ are always available. They are listed here in alphabetical order.
care about trailing, unmatched values from the longer iterables. If those
values are important, use :func:`itertools.zip_longest` instead.
:func:`zip` in conjunction with the ``*`` operator can be used to unzip a
list::
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> zipped = zip(x, y)
>>> zipped
[(1, 4), (2, 5), (3, 6)]
>>> x2, y2 = zip(*zipped)
>>> x == x2, y == y2
True
.. rubric:: Footnotes

View File

@@ -25,7 +25,7 @@ represents the database. Here the data will be stored in the
You can also supply the special name ``:memory:`` to create a database in RAM.
Once you have a :class:`Connection`, you can create a :class:`Cursor` object
and call its :meth:`execute` method to perform SQL commands::
and call its :meth:`~Cursor.execute` method to perform SQL commands::
c = conn.cursor()
@@ -50,7 +50,7 @@ is insecure; it makes your program vulnerable to an SQL injection attack.
Instead, use the DB-API's parameter substitution. Put ``?`` as a placeholder
wherever you want to use a value, and then provide a tuple of values as the
second argument to the cursor's :meth:`execute` method. (Other database modules
second argument to the cursor's :meth:`~Cursor.execute` method. (Other database modules
may use a different placeholder, such as ``%s`` or ``:1``.) For example::
# Never do this -- insecure!
@@ -69,8 +69,8 @@ may use a different placeholder, such as ``%s`` or ``:1``.) For example::
c.execute('insert into stocks values (?,?,?,?,?)', t)
To retrieve data after executing a SELECT statement, you can either treat the
cursor as an :term:`iterator`, call the cursor's :meth:`fetchone` method to
retrieve a single matching row, or call :meth:`fetchall` to get a list of the
cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to
retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the
matching rows.
This example uses the iterator form::
@@ -128,7 +128,7 @@ Module functions and constants
returns. It will look for a string formed [mytype] in there, and then decide
that 'mytype' is the type of the column. It will try to find an entry of
'mytype' in the converters dictionary and then use the converter function found
there to return the value. The column name found in :attr:`cursor.description`
there to return the value. The column name found in :attr:`Cursor.description`
is only the first word of the column name, i. e. if you use something like
``'as "x [datetime]"'`` in your SQL, then we will parse out everything until the
first blank for the column name: the column name would simply be "x".
@@ -215,11 +215,13 @@ Module functions and constants
Connection Objects
------------------
A :class:`Connection` instance has the following attributes and methods:
.. class:: Connection
A SQLite database connection has the following attributes and methods:
.. attribute:: Connection.isolation_level
Get or set the current isolation level. None for autocommit mode or one of
Get or set the current isolation level. :const:`None` for autocommit mode or one of
"DEFERRED", "IMMEDIATE" or "EXLUSIVE". See section
:ref:`sqlite3-controlling-transactions` for a more detailed explanation.
@@ -234,7 +236,7 @@ A :class:`Connection` instance has the following attributes and methods:
.. method:: Connection.commit()
This method commits the current transaction. If you don't call this method,
anything you did since the last call to commit() is not visible from from
anything you did since the last call to ``commit()`` is not visible from from
other database connections. If you wonder why you don't see the data you've
written to the database, please check you didn't forget to call this method.
@@ -383,9 +385,9 @@ A :class:`Connection` instance has the following attributes and methods:
.. attribute:: Connection.text_factory
Using this attribute you can control what objects are returned for the TEXT data
type. By default, this attribute is set to :class:`str` and the
:mod:`sqlite3` module will return strings for TEXT. If you want to
Using this attribute you can control what objects are returned for the ``TEXT``
data type. By default, this attribute is set to :class:`str` and the
:mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to
return bytestrings instead, you can set it to :class:`bytes`.
For efficiency reasons, there's also a way to return :class:`str` objects
@@ -430,8 +432,9 @@ A :class:`Connection` instance has the following attributes and methods:
Cursor Objects
--------------
A :class:`Cursor` instance has the following attributes and methods:
.. class:: Cursor
A SQLite database cursor has the following attributes and methods:
.. method:: Cursor.execute(sql, [parameters])
@@ -470,7 +473,7 @@ A :class:`Cursor` instance has the following attributes and methods:
.. method:: Cursor.executescript(sql_script)
This is a nonstandard convenience method for executing multiple SQL statements
at once. It issues a COMMIT statement first, then executes the SQL script it
at once. It issues a ``COMMIT`` statement first, then executes the SQL script it
gets as a parameter.
*sql_script* can be an instance of :class:`str` or :class:`bytes`.
@@ -483,7 +486,7 @@ A :class:`Cursor` instance has the following attributes and methods:
.. method:: Cursor.fetchone()
Fetches the next row of a query result set, returning a single sequence,
or ``None`` when no more data is available.
or :const:`None` when no more data is available.
.. method:: Cursor.fetchmany([size=cursor.arraysize])
@@ -522,8 +525,8 @@ A :class:`Cursor` instance has the following attributes and methods:
into :attr:`rowcount`.
As required by the Python DB API Spec, the :attr:`rowcount` attribute "is -1 in
case no executeXX() has been performed on the cursor or the rowcount of the last
operation is not determinable by the interface".
case no ``executeXX()`` has been performed on the cursor or the rowcount of the
last operation is not determinable by the interface".
This includes ``SELECT`` statements because we cannot determine the number of
rows a query produced until all rows were fetched.
@@ -535,6 +538,81 @@ A :class:`Cursor` instance has the following attributes and methods:
method. For operations other than ``INSERT`` or when :meth:`executemany` is
called, :attr:`lastrowid` is set to :const:`None`.
.. attribute:: Cursor.description
This read-only attribute provides the column names of the last query. To
remain compatible with the Python DB API, it returns a 7-tuple for each
column where the last six items of each tuple are :const:`None`.
It is set for ``SELECT`` statements without any matching rows as well.
.. _sqlite3-row-objects:
Row Objects
-----------
.. class:: Row
A :class:`Row` instance serves as a highly optimized
:attr:`~Connection.row_factory` for :class:`Connection` objects.
It tries to mimic a tuple in most of its features.
It supports mapping access by column name and index, iteration,
representation, equality testing and :func:`len`.
If two :class:`Row` objects have exactly the same columns and their
members are equal, they compare equal.
.. versionchanged:: 2.6
Added iteration and equality (hashability).
.. method:: keys
This method returns a tuple of column names. Immediately after a query,
it is the first member of each tuple in :attr:`Cursor.description`.
.. versionadded:: 2.6
Let's assume we initialize a table as in the example given above::
conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
conn.commit()
c.close()
Now we plug :class:`Row` in::
>>> conn.row_factory = sqlite3.Row
>>> c = conn.cursor()
>>> c.execute('select * from stocks')
<sqlite3.Cursor object at 0x7f4e7dd8fa80>
>>> r = c.fetchone()
>>> type(r)
<type 'sqlite3.Row'>
>>> r
(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.140000000000001)
>>> len(r)
5
>>> r[2]
u'RHAT'
>>> r.keys()
['date', 'trans', 'symbol', 'qty', 'price']
>>> r['qty']
100.0
>>> for member in r: print member
...
2006-01-05
BUY
RHAT
100.0
35.14
.. _sqlite3-types:
SQLite and Python types
@@ -544,36 +622,38 @@ SQLite and Python types
Introduction
^^^^^^^^^^^^
SQLite natively supports the following types: NULL, INTEGER, REAL, TEXT, BLOB.
SQLite natively supports the following types: ``NULL``, ``INTEGER``,
``REAL``, ``TEXT``, ``BLOB``.
The following Python types can thus be sent to SQLite without any problem:
+-------------------------------+-------------+
| Python type | SQLite type |
+===============================+=============+
| ``None`` | NULL |
| :const:`None` | ``NULL`` |
+-------------------------------+-------------+
| :class:`int` | INTEGER |
| :class:`int` | ``INTEGER`` |
+-------------------------------+-------------+
| :class:`float` | REAL |
| :class:`float` | ``REAL`` |
+-------------------------------+-------------+
| :class:`bytes` (UTF8-encoded) | TEXT |
| :class:`bytes` (UTF8-encoded) | ``TEXT`` |
+-------------------------------+-------------+
| :class:`str` | TEXT |
| :class:`str` | ``TEXT`` |
+-------------------------------+-------------+
| :class:`buffer` | BLOB |
| :class:`buffer` | ``BLOB`` |
+-------------------------------+-------------+
This is how SQLite types are converted to Python types by default:
+-------------+---------------------------------------------+
| SQLite type | Python type |
+=============+=============================================+
| ``NULL`` | None |
| ``NULL`` | :const:`None` |
+-------------+---------------------------------------------+
| ``INTEGER`` | int |
| ``INTEGER`` | :class`int` |
+-------------+---------------------------------------------+
| ``REAL`` | float |
| ``REAL`` | :class:`float` |
+-------------+---------------------------------------------+
| ``TEXT`` | depends on text_factory, str by default |
+-------------+---------------------------------------------+
@@ -701,9 +781,10 @@ Controlling Transactions
------------------------
By default, the :mod:`sqlite3` module opens transactions implicitly before a
Data Modification Language (DML) statement (i.e. INSERT/UPDATE/DELETE/REPLACE),
and commits transactions implicitly before a non-DML, non-query statement (i. e.
anything other than SELECT/INSERT/UPDATE/DELETE/REPLACE).
Data Modification Language (DML) statement (i.e.
``INSERT``/``UPDATE``/``DELETE``/``REPLACE``), and commits transactions
implicitly before a non-DML, non-query statement (i. e.
anything other than ``SELECT`` or the aforementioned).
So if you are within a transaction and issue a command like ``CREATE TABLE
...``, ``VACUUM``, ``PRAGMA``, the :mod:`sqlite3` module will commit implicitly
@@ -712,7 +793,7 @@ is that some of these commands don't work within transactions. The other reason
is that pysqlite needs to keep track of the transaction state (if a transaction
is active or not).
You can control which kind of "BEGIN" statements pysqlite implicitly executes
You can control which kind of ``BEGIN`` statements pysqlite implicitly executes
(or none at all) via the *isolation_level* parameter to the :func:`connect`
call, or via the :attr:`isolation_level` property of connections.
@@ -736,7 +817,7 @@ Using the nonstandard :meth:`execute`, :meth:`executemany` and
be written more concisely because you don't have to create the (often
superfluous) :class:`Cursor` objects explicitly. Instead, the :class:`Cursor`
objects are created implicitly and these shortcut methods return the cursor
objects. This way, you can execute a SELECT statement and iterate over it
objects. This way, you can execute a ``SELECT`` statement and iterate over it
directly using only a single call on the :class:`Connection` object.
.. literalinclude:: ../includes/sqlite3/shortcut_methods.py

View File

@@ -334,8 +334,8 @@ Replacing /bin/sh shell backquote
output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]
Replacing shell pipe line
^^^^^^^^^^^^^^^^^^^^^^^^^
Replacing shell pipeline
^^^^^^^^^^^^^^^^^^^^^^^^
::

View File

@@ -775,9 +775,9 @@ can appear before a future statement are:
.. XXX change this if future is cleaned out
The features recognized by Python 3.0 are ``absolute_import``, ``division``,
``generators``, ``nested_scopes`` and ``with_statement``. They are all
redundant because they are always enabled, and only kept for backwards
compatibility.
``generators``, ``unicode_literals``, ``print_function``, ``nested_scopes`` and
``with_statement``. They are all redundant because they are always enabled, and
only kept for backwards compatibility.
A future statement is recognized and treated specially at compile time: Changes
to the semantics of core constructs are often implemented by generating

View File

@@ -31,8 +31,8 @@ in the table are the size of the download files in Kilobytes.</p>
<td><a href="{{ dlbase }}/python-docs-html.tar.bz2">Download</a> (ca. 4 MB)</td>
</tr>
<tr><td>Plain Text</td>
<td><a href="{{ dlbase }}/python-docs-pdf-text.zip">Download</a> (ca. 2 MB)</td>
<td><a href="{{ dlbase }}/python-docs-pdf-text.tar.bz2">Download</a> (ca. 1.5 MB)</td>
<td><a href="{{ dlbase }}/python-docs-text.zip">Download</a> (ca. 2 MB)</td>
<td><a href="{{ dlbase }}/python-docs-text.tar.bz2">Download</a> (ca. 1.5 MB)</td>
</tr>
</table>

View File

@@ -4,7 +4,7 @@
<table class="contentstable" align="center"><tr>
<td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version) }}">What's new in Python {{ version }}?</a><br/>
<span class="linkdescr">changes since previous major release</span></p>
<span class="linkdescr">or <a href="{{ pathto("whatsnew/index") }}">all "What's new" documents</a> since 2.0</span></span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("tutorial/index") }}">Tutorial</a><br/>
<span class="linkdescr">start here</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("using/index") }}">Using Python</a><br/>

View File

@@ -1,5 +1,4 @@
{% extends "!layout.html" %}
{% block rootrellink %}
<li><img src="{{ pathto('_static/py.png', 1) }}" alt="" style="vertical-align: middle; margin-top: -1px"/></li>
{{ super() }}
<li><img src="{{ pathto('_static/py.png', 1) }}" alt="" style="vertical-align: middle; margin-top: -1px"/></li><li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
{% endblock %}

View File

@@ -714,7 +714,7 @@ Python's division operator, ``/``, behaves like C's division operator when
presented with two integer arguments: it returns an integer result that's
truncated down when there would be a fractional part. For example, ``3/2`` is
1, not 1.5, and ``(-1)/2`` is -1, not -0.5. This means that the results of
divison can vary unexpectedly depending on the type of the two operands and
division can vary unexpectedly depending on the type of the two operands and
because Python is dynamically typed, it can be difficult to determine the
possible types of the operands.

View File

@@ -1196,7 +1196,7 @@ Optimizations
* The ``SET_LINENO`` opcode is now gone. This may provide a small speed
increase, depending on your compiler's idiosyncrasies. See section
:ref:`section-other` for a longer explanation. (Removed by Michael Hudson.)
:ref:`23section-other` for a longer explanation. (Removed by Michael Hudson.)
* :func:`xrange` objects now have their own iterator, making ``for i in
xrange(n)`` slightly faster than ``for i in range(n)``. (Patch by Raymond
@@ -1951,7 +1951,7 @@ Other new platforms now supported by Python include AtheOS
.. ======================================================================
.. _section-other:
.. _23section-other:
Other Changes and Fixes
=======================
@@ -2062,7 +2062,7 @@ code:
.. ======================================================================
.. _acks:
.. _23acks:
Acknowledgements
================

View File

@@ -1551,7 +1551,7 @@ code:
.. ======================================================================
.. _acks:
.. _24acks:
Acknowledgements
================

View File

@@ -16,9 +16,9 @@ release schedule.
The changes in Python 2.5 are an interesting mix of language and library
improvements. The library enhancements will be more important to Python's user
community, I think, because several widely-useful packages were added. New
modules include ElementTree for XML processing (section :ref:`module-etree`),
the SQLite database module (section :ref:`module-sqlite`), and the :mod:`ctypes`
module for calling C functions (section :ref:`module-ctypes`).
modules include ElementTree for XML processing (:mod:`xml.etree`),
the SQLite database module (:mod:`sqlite`), and the :mod:`ctypes`
module for calling C functions.
The language changes are of middling significance. Some pleasant new features
were added, but most of them aren't features that you'll use every day.
@@ -736,7 +736,7 @@ add a :keyword:`return` statement at the marked location. ::
# return False
.. _module-contextlib:
.. _contextlibmod:
The contextlib module
---------------------
@@ -1109,7 +1109,7 @@ Here are all of the changes that Python 2.5 makes to the core Python language.
.. ======================================================================
.. _interactive:
.. _25interactive:
Interactive Interpreter Changes
-------------------------------
@@ -1211,7 +1211,7 @@ marked in the following list.
.. ======================================================================
.. _modules:
.. _25modules:
New, Improved, and Removed Modules
==================================
@@ -1273,7 +1273,7 @@ complete list of changes, or look through the SVN logs for all the details.
(Contributed by Raymond Hettinger.)
* New module: The :mod:`contextlib` module contains helper functions for use
with the new ':keyword:`with`' statement. See section :ref:`module-contextlib`
with the new ':keyword:`with`' statement. See section :ref:`contextlibmod`
for more about this module.
* New module: The :mod:`cProfile` module is a C implementation of the existing
@@ -2272,8 +2272,6 @@ code:
.. ======================================================================
.. _acks:
Acknowledgements
================

File diff suppressed because it is too large Load Diff

138
Doc/whatsnew/2.7.rst Normal file
View File

@@ -0,0 +1,138 @@
****************************
What's New in Python 2.7
****************************
:Author: A.M. Kuchling (amk at amk.ca)
:Release: |release|
:Date: |today|
.. $Id$
Rules for maintenance:
* Anyone can add text to this document. Do not spend very much time
on the wording of your changes, because your text will probably
get rewritten to some degree.
* The maintainer will go through Misc/NEWS periodically and add
changes; it's therefore more important to add your changes to
Misc/NEWS than to this file.
* This is not a complete list of every single change; completeness
is the purpose of Misc/NEWS. Some changes I consider too small
or esoteric to include. If such a change is added to the text,
I'll just remove it. (This is another reason you shouldn't spend
too much time on writing your addition.)
* If you want to draw your new text to the attention of the
maintainer, add 'XXX' to the beginning of the paragraph or
section.
* It's OK to just add a fragmentary note about a change. For
example: "XXX Describe the transmogrify() function added to the
socket module." The maintainer will research the change and
write the necessary text.
* You can comment out your additions if you like, but it's not
necessary (especially when a final release is some months away).
* Credit the author of a patch or bugfix. Just the name is
sufficient; the e-mail address isn't necessary.
* It's helpful to add the bug/patch number in a parenthetical comment.
XXX Describe the transmogrify() function added to the socket
module.
(Contributed by P.Y. Developer; :issue:`12345`.)
This saves the maintainer some effort going through the SVN logs
when researching a change.
This article explains the new features in Python 2.7.
No release schedule has been decided yet for 2.7.
.. Compare with previous release in 2 - 3 sentences here.
add hyperlink when the documentation becomes available online.
.. ========================================================================
.. Large, PEP-level features and changes should be described here.
.. Should there be a new section here for 3k migration?
.. Or perhaps a more general section describing module changes/deprecation?
.. ========================================================================
Other Language Changes
======================
Some smaller changes made to the core Python language are:
* List of changes to be written here.
.. ======================================================================
Optimizations
-------------
To be written.
.. ======================================================================
New, Improved, and Deprecated Modules
=====================================
As in every release, Python's standard library received a number of
enhancements and bug fixes. Here's a partial list of the most notable
changes, sorted alphabetically by module name. Consult the
:file:`Misc/NEWS` file in the source tree for a more complete list of
changes, or look through the Subversion logs for all the details.
* To be written.
.. ======================================================================
.. whole new modules get described in subsections here
.. ======================================================================
Build and C API Changes
=======================
Changes to Python's build process and to the C API include:
* To be written.
.. ======================================================================
Port-Specific Changes: Windows
-----------------------------------
.. ======================================================================
Port-Specific Changes: Mac OS X
-----------------------------------
.. ======================================================================
Porting to Python 2.7
=====================
This section lists previously described changes and other bugfixes
that may require changes to your code:
To be written.
.. ======================================================================
.. _acks27:
Acknowledgements
================
The author would like to thank the following people for offering
suggestions, corrections and assistance with various drafts of this
article: no one yet.

View File

@@ -440,7 +440,7 @@ Platform-specific changes go here.
.. ======================================================================
.. _section-other:
.. _30section-other:
Other Changes and Fixes
=======================

22
Doc/whatsnew/index.rst Normal file
View File

@@ -0,0 +1,22 @@
.. _whatsnew-index:
######################
What's New in Python
######################
The "What's New in Python" series of essays takes tours through the most
important changes between major Python versions. They are a "must read" for
anyone wishing to stay up-to-date after a new release.
.. toctree::
:maxdepth: 1
3.0.rst
2.7.rst
2.6.rst
2.5.rst
2.4.rst
2.3.rst
2.2.rst
2.1.rst
2.0.rst

Some files were not shown because too many files have changed in this diff Show More