Ваш веб-сервер работает с обычным пользователем www-data
(который принадлежит группе www-data
), в то время как ваш консольный вызов PHPUnit создал кэш с пользователем и группой вашего пользователя оболочки. Это распространено и не должно вызывать удивления - почему пользователь оболочки должен иметь возможность записывать данные, используя другого пользователя?
Самое простое решение - использовать разные среды, так как вы также можете использовать разные настройки для запуска тестов. или доступ к предоставленным веб-сайтам.
Если вы не хотите использовать разные среды, в документации Symfony есть несколько идей для вашего:
www-data
и вашего пользователя оболочки были полные права доступа) Будет ли что-то подобное делать то, что вам нужно?
class Test(object):
def _decorator(foo):
def magic( self ) :
print "start magic"
foo( self )
print "end magic"
return magic
@_decorator
def bar( self ) :
print "normal call"
test = Test()
test.bar()
Это позволяет избежать вызова self для доступа к декоратору и оставляет его скрытым в пространстве имен класса как обычный метод.
>>> import stackoverflow
>>> test = stackoverflow.Test()
>>> test.bar()
start magic
normal call
end magic
>>>
отредактировано в ответьте на вопрос в комментариях:
Как использовать скрытый декоратор в другом классе
class Test(object):
def _decorator(foo):
def magic( self ) :
print "start magic"
foo( self )
print "end magic"
return magic
@_decorator
def bar( self ) :
print "normal call"
_decorator = staticmethod( _decorator )
class TestB( Test ):
@Test._decorator
def bar( self ):
print "override bar in"
super( TestB, self ).bar()
print "override bar out"
print "Normal:"
test = Test()
test.bar()
print
print "Inherited:"
b = TestB()
b.bar()
print
Вывод:
Normal:
start magic
normal call
end magic
Inherited:
start magic
override bar in
start magic
normal call
end magic
override bar out
end magic
Объявите во внутреннем классе. Этот раствор довольно тверд и рекомендован.
class Test(object):
class Decorators(object):
@staticmethod
def decorator(foo):
def magic(self, *args, **kwargs) :
print("start magic")
foo(self, *args, **kwargs)
print("end magic")
return magic
@Decorators.decorator
def bar( self ) :
print("normal call")
test = Test()
test.bar()
результат:
>>> test = Test()
>>> test.bar()
start magic
normal call
end magic
>>>
То, что вы хотите сделать, невозможно. Возьмем, например, выглядит ли приведенный ниже код действительным или нет:
class Test(object):
def _decorator(self, foo):
foo()
def bar(self):
pass
bar = self._decorator(bar)
Он, конечно, недействителен, поскольку self
не определен в этой точке. То же самое касается Test
, поскольку он не будет определен, пока не будет определен сам класс (который находится в процессе). Я показываю вам этот фрагмент кода, потому что это то, во что преобразуется фрагмент вашего декоратора.
Итак, как вы можете видеть, доступ к экземпляру в таком декораторе на самом деле невозможен, поскольку декораторы применяются во время определение любой функции / метода, к которым они прикреплены, а не во время создания.
Если вам нужен доступ на уровне класса , попробуйте следующее:
class Test(object):
@classmethod
def _decorator(cls, foo):
foo()
def bar(self):
pass
Test.bar = Test._decorator(Test.bar)