Skip to content

bpo-30486: Allow setting cell value#1840

Merged
serhiy-storchaka merged 10 commits into
python:masterfrom
lisroach:issue30486
Jun 8, 2017
Merged

bpo-30486: Allow setting cell value#1840
serhiy-storchaka merged 10 commits into
python:masterfrom
lisroach:issue30486

Conversation

@lisroach

Copy link
Copy Markdown
Contributor

No description provided.

@mention-bot

Copy link
Copy Markdown

@lisroach, thanks for your PR! By analyzing the history of the files in this pull request, we identified @warsaw, @Yhg1s and @tiran to be potential reviewers.

@codecov

codecov Bot commented May 28, 2017

Copy link
Copy Markdown

Codecov Report

Merging #1840 into master will decrease coverage by 1.02%.
The diff coverage is 94.44%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1840      +/-   ##
==========================================
- Coverage   83.68%   82.65%   -1.03%     
==========================================
  Files        1371     1432      +61     
  Lines      347053   353644    +6591     
==========================================
+ Hits       290428   292307    +1879     
- Misses      56625    61337    +4712
Impacted Files Coverage Δ
Lib/test/test_funcattrs.py 92.55% <94.44%> (+0.12%) ⬆️
Lib/lib2to3/fixes/fix_ws_comma.py 41.66% <0%> (-58.34%) ⬇️
Lib/lib2to3/tests/test_all_fixers.py 66.66% <0%> (-25%) ⬇️
Lib/lib2to3/pytree.py 84.91% <0%> (-5.84%) ⬇️
Lib/lib2to3/tests/support.py 87.09% <0%> (-3.23%) ⬇️
Lib/test/test_io.py 94.97% <0%> (-1.98%) ⬇️
Lib/test/test_faulthandler.py 93.85% <0%> (-1.22%) ⬇️
Lib/logging/handlers.py 83.38% <0%> (-0.53%) ⬇️
Lib/test/datetimetester.py 95.84% <0%> (-0.48%) ⬇️
Lib/lib2to3/refactor.py 80.17% <0%> (-0.44%) ⬇️
... and 92 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 178418a...bd5e329. Read the comment docs.

@rhettinger rhettinger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tests and documentation updates.

Comment thread Objects/cellobject.c Outdated
cell_set_contents(PyCellObject *op, PyCellObject *obj)
{
Py_INCREF(obj);
PyCellObject *tmp_op = (PyCellObject *)(op->ob_ref);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the 147 to 149 can be replace by a single invocation of the Py_SETREF macro. See +856 in Include/object.h.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I originally had in my first commit, but running make patchcheck showed this warning:
incompatible pointer types assigning to 'PyObject *' (aka 'struct _object *') from 'PyCellObject *'

Which is why I rewrote with the current lines. What do you think?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about

Py_XSETREF(op->ob_ref, (PyObject *)obj);

?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may have used the macro incorrectly. Did you try Py_SETREF(op->ob_ref, obj)?
Actually, you need Py_XSETREF (and Py_XINCREF), since obj can be NULL as @serhiy-storchaka pointed out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@serhiy-storchaka is right, the correct syntax is
Py_XSETREF(op->ob_ref, (PyObject *)obj);

But after looking at it more I obj should be a PyObject anyway and not a PyCellObject. I am new at C though so I could be wrong!

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to requested code changes, needed tests and an entry in Misc/NEWS (maybe even in What's New).

Comment thread Objects/cellobject.c Outdated
int
cell_set_contents(PyCellObject *op, PyCellObject *obj)
{
Py_INCREF(obj);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obj can be NULL (when delete the attribute: del cell.cell_contents).

@Mariatta Mariatta added the type-feature A feature request or enhancement label May 29, 2017
Comment thread Objects/cellobject.c Outdated
int
cell_set_contents(PyCellObject *op, PyObject *obj)
{
if (obj == Py_None)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None is a legal value for the cell value.

Comment thread Lib/test/test_funcattrs.py Outdated
c = f.__closure__
c[0].cell_contents = 9
self.assertEqual(c[0].cell_contents, 9)
c[0].cell_contents = None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None is a legal value for the cell value.

You should test

del c[0].cell_contents

Comment thread Doc/reference/datamodel.rst Outdated
| | attributes. | |
+-------------------------+-------------------------------+-----------+
| :attr:`__closure__` | ``None`` or a tuple of cells | Read-only |
| :attr:`__closure__` | ``None`` or a tuple of cells | Writable |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __closure__ attribute is not writable. The undocumented cell_contents attribute of __closure__ elements is writable.

Comment thread Lib/test/test_funcattrs.py Outdated

def test_set_cell(self):
a = 12
def f(): print(a)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use def f(): return a instead, you could verify that calling f() does return the updated value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a blocker to getting this accepted, btw, just nice to have ;-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good idea!

def f(): print(a)
c = f.__closure__
c[0].cell_contents = 9
self.assertEqual(c[0].cell_contents, 9)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to check how setting and deleting cell_contents affects the local variable a.

Comment thread Doc/reference/datamodel.rst Outdated
| | function's free variables. | |
| | The ``cell_contents`` | |
| | attribute can be used for | |
| | used for reading and writing | |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated "used for".

It may be better to describe the cell object somewhere else (for example in a footnote or in a separate paragraph following this table) than in a narrow table cell.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is kind of awkward trying to fit it in the table, I'll try to put it somewhere below.

can be used, for example, to attach metadata to functions. Regular attribute
dot-notation is used to get and set such attributes. *Note that the current
implementation only supports function attributes on user-defined functions.
Function attributes on built-in functions may be supported in the future.*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed * (it needs for ending an emphasizing of a note).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the * in front of Note as well?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just restore removed * here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh oops, sorry I didn't realize I had deleted that!

c = f.__closure__
c[0].cell_contents = 9
self.assertEqual(c[0].cell_contents, 9)
self.assertEqual(f(), 9)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check a directly.

self.assertEqual(a, 9)

self.assertEqual(c[0].cell_contents, 9)
self.assertEqual(f(), 9)
del c[0].cell_contents
try:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that you have copied an example from the above test, but this is too verbose. with self.assertRaises(ValueError): is much more compact.

else:
self.fail("shouldn't be able to read an empty cell")
try:
with self.assertRaises(NameError):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check a directly.

@serhiy-storchaka
serhiy-storchaka merged commit 64505a1 into python:master Jun 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants