Closed TezRomacH closed 5 years ago
moreover, if I remove one of them, i will be able to import the module, but neither setter
nor deleter
won't work and will not raise ValueError
Thank you for the bug report, this is an example of doing things too early. Long story short, I transformed the module and the property itself too early, and it's trying to fetch the property in order to set the setter.
On your side, your setter/deleter calls are wrong in the context of Python properties (they won't work the way you seem to expect, even with regular properties on a class). This below works with the updated and released 0.16.0, available now at PyPI and here on the master branch.
from typing import NoReturn
from mprop import mproperty
class _relative:
def __str__(self) -> str:
return "*"
_relative_instance = _relative()
@mproperty
def relative(module):
return _relative_instance
@relative.setter
def relative(module, value) -> NoReturn:
raise ValueError("Cannot set a value into relative")
@relative.deleter
def relative(module, deleter) -> NoReturn:
raise ValueError("Cannot delete relative")
But really, if all you wanted to do was to prevent the assignment, that already works with the way properties normally work. No setter, can't set. No deleter, can't delete.
#example3.py
import mprop
@mprop.mproperty
def foo(self):
return "hello"
In a console:
$ python3.6
Python 3.6.3 (default, Apr 4 2018, 14:57:55)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example3
>>> example3.foo
'hello'
>>> example3.foo = 'bar'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> del example3.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't delete attribute
Thank you again for the bug report.
Thank you for a quick response. I found interesting details about mproperty
. Pip version == 0.16.0
My module was organized like:
safitty/
__init__.py
core.py
In core
module I created property without any setter and deleter as you note before.
@mprop.mproperty
def relative(module):
return _relative_instance
and then in __init__.py
:
from safitty.core import relative
__all__ = ['relative']
with this, after import my module I still able to delete and set any value. But if I move the definition of relative
into __init__.py
:
@mprop.mproperty
def relative(module):
return _relative_instance
__all__ = ['relative']
Everything works well. Is this the expected behavior?
The behavior you report is expected by me. If you want to expect it too, you can read the descriptor docs listed in 1 below, or believe me in that it implies 2 and 3, and explains why you get what you get. I have added the additional semantics in 4 with this library, which further explains.
from x import y
inside of file z.py
means you look up the attribute / descriptor y
on x
once, then you cache the reference inside z
y
is no longer a descriptor when accessed from the importing module z
, but is still a descriptor when accessed via x.y
from z
or anywhere else that imported x
.y
from inside x
as a property, use _pmodule.y
, because you still need an object context to get a descriptor properly.
I would like to create a one global module property with the getter but without setter and deleter.
I run this simple code
But when i try to import my module i got an error
I tried to change the order of functions and create
_deleter
before_setter
: