Giter VIP home page Giter VIP logo

venusian's Introduction

venusian

image

Documentation Status

Venusian is a library which allows framework authors to defer decorator actions. Instead of taking actions when a function (or class) decorator is executed at import time, you can defer the action usually taken by the decorator until a separate "scan" phase.

See the "docs" directory of the package or the online documentation at https://docs.pylonsproject.org/projects/venusian/en/latest/

venusian's People

Contributors

bluefish6 avatar dependabot[bot] avatar di avatar digitalresistor avatar fcorrea avatar felixonmars avatar ferdnyc avatar fschulze avatar gjo avatar jbohman avatar jugmac00 avatar julienpalard avatar lorenzogil avatar lrowe avatar mcdonc avatar mmerickel avatar msabramo avatar oohlaf avatar pieterproigia avatar robinharms avatar stevepiercy avatar tseaver avatar tshepang avatar wichert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

venusian's Issues

Python 3.12 -- FileFinder

'FileFinder' object has no attribute 'find_module',

Is it not supported anymore?
Is there a work around beside downgrading?

view_config registers twice if module is imported more than once with scan

Not sure this is the right tracker for this, but I suspect it's a venusian issue at the core...

So, I have a view defined as a class:

@view_config(...)
class MyView(...):
...

I have another module (a test module as it happens, and yes I know importing from code under test at module level is evil in some peoples' eyes, but it's certainly legit to import from a module that contains a view class with a view_config decorator, and I believe that will trigger the same problem) that imports the view class and that import, at the time of the config.scan() appears to cause a duplicate registration of the following form:

ConfigurationConflictError: Conflicting configuration actions
For: ('view', None, '', None, , None, None, None, 'user', None, False, None, None, None)
('...views.py', 119, '', 'class MyView(...):')
('...views.py', 119, '', 'class MyView(...):')

My gut feels it that view_config (and likely any venusian thing) should do nothing if the thing it's decorating has already been visited...

venusian attributes and inheritance

I don't think venusian callback attributes are handled correctly when used for class decorators ... The implementation seems inconsistent and its unclear to me how this design might actually be used ... With the current implementation I can't use class decorators on a superclass and expect the handler to be added to subclasses and neither can I reliably use the same decorator on a superclass and a subclass.

Using a class decorator on a superclass and at least one subclass means all super/subclasses share the venusian callbacks:

@decorate 
class SuperClass: 
 pass

@decorate 
class SubClass(SuperClass):
 pass

class OtherSubClass(SuperClass):
 pass

OtherSubClass.__venusian_callbacks__ == SubClass.__venusian_callbacks__ == SuperClass.__venusian_callbacks__

Using a class decorator on a superclass and no subclasses means only the superclass gets the callbacks:

@decorate 
class SuperClass: 
 pass

class SubClass(SuperClass):
 pass

class OtherSubClass(SuperClass):
 pass

Subclass.__venusian_callbacks__

raises attribute error. It seems to me there's no effective way to deliberately use venusian for class decoration ... I can't implement a design where a decorated class and all its subclasses are automatically decorated and found during a venusian scan -- and neither can I manually apply the same decoration to all the subclass objects as it results in many callbacks being registered in the shared attribute array of each sub and superclass ... I would argue that this is a bug but maybe I'm just not seeing an effective way to use this?

Thanks

Loader error on Python 3.4

This might be related to #19. When running tests under Python 3.4.1 on CircleCI I get this error:

 ERROR at setup of test_update_status_response[postgresql:///circle_test-False] 
tests/backend/conftest.py:12: in app
    app = main({})
/home/ubuntu/virtualenvs/venv-3.4.1/lib/python3.4/site-packages/jzoo_backend-1.0.0-py3.4.egg/jzoo/backend/app.py:49: in main
    config.scan('jzoo.backend')
../virtualenvs/venv-3.4.1/src/pyramid-fix.view-lookup/pyramid/config/__init__.py:959: in scan
    ignore=ignore)
../virtualenvs/venv-3.4.1/lib/python3.4/site-packages/venusian/__init__.py:195: in scan
    fn = loader.get_filename()
E   TypeError: zipimporter.get_filename() takes exactly 1 argument (0 given)

scan an individual module

I have a need for a method scan_module() that scans just a single module and does not recurse down packages. So it is related to issue #7 from 2011, I think.

I've factored an invoke() and a scan_module() method out of scan(). I think this also makes the code more readable as a whole.

The tests pass on Python 2.6 and Python 2.7, but the test runner (before my changes) has issues with both PyPy and Python 3.3, see issues #35 and #36. Once those get fixed I can send a pull request.

Compiler error messages when trying to install on 2.5

When trying to install venusian 1.0a11 on Python 2.5 I get the following error messages:

(tempenv)notroot@debian:/tmp/tempenv/bin$ easy_install venusian
Searching for venusian
Reading http://pypi.python.org/simple/venusian/
Reading http://pylonsproject.org
Reading http://www.repoze.org
Best match: venusian 1.0a1
Downloading http://pypi.python.org/packages/source/v/venusian/venusian-1.0a1.tar.gz#md5=7fafec2c2dee07991cffbf9fd2b31ec3
Processing venusian-1.0a1.tar.gz
Running venusian-1.0a1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-0lXRQg/venusian-1.0a1/egg-dist-tmp-2mwK5m
File "build/bdist.linux-x86_64/egg/venusian/tests/fixtures/classdecorator.py", line 4
class SuperClass(object):
^
SyntaxError: invalid syntax

File "build/bdist.linux-x86_64/egg/venusian/tests/fixtures/two/mod1.py", line 4
class Class(object):
^
SyntaxError: invalid syntax

File "build/bdist.linux-x86_64/egg/venusian/tests/fixtures/inheritance.py", line 4
class Parent(object):
^
SyntaxError: invalid syntax

File "/tmp/tempenv/lib/python2.5/site-packages/venusian-1.0a1-py2.5.egg/venusian/tests/fixtures/classdecorator.py", line 4
class SuperClass(object):
^
SyntaxError: invalid syntax

File "/tmp/tempenv/lib/python2.5/site-packages/venusian-1.0a1-py2.5.egg/venusian/tests/fixtures/inheritance.py", line 4
class Parent(object):
^
SyntaxError: invalid syntax

File "/tmp/tempenv/lib/python2.5/site-packages/venusian-1.0a1-py2.5.egg/venusian/tests/fixtures/two/mod1.py", line 4
class Class(object):
^
SyntaxError: invalid syntax

Adding venusian 1.0a1 to easy-install.pth file

Installed /tmp/tempenv/lib/python2.5/site-packages/venusian-1.0a1-py2.5.egg
Processing dependencies for venusian
Finished processing dependencies for venusian

breaks with unittest.mock.call

For some reason, our pyramid project crashes with the following error when there is a from unittest.mock import call statement. Instead if its from unittest import mock it works as intended.

Traceback (most recent call last):
  File "[removed]", line 157, in setUpClass
    cls.wsgi = [removed].main(None, **cls.settings)
  File "[removed]", line 71, in main
    config.scan()
  File "[removed]/venv/lib/python3.3/site-packages/pyramid-1.4.2-py3.3.egg/pyramid/config/__init__.py", line 947, in scan
    ignore=ignore)
  File "[removed]/venv/lib/python3.3/site-packages/venusian-1.0a8-py3.3.egg/venusian/__init__.py", line 208, in scan
    invoke(modname, name, ob)
  File "[removed]/venv/lib/python3.3/site-packages/venusian-1.0a8-py3.3.egg/venusian/__init__.py", line 159, in invoke
    category_keys.sort()
TypeError: unorderable types: tuple() < str()

For now, we're using the workaround mentioned, but I figured it would be nice to report the issue.

Basic usage question

I'm using the venusian docs, trying to copy closely and make this simplest demo I can. I expect the result '{"x": 1}' but I'm getting {'x': 1}, which isn't jsonified.

If I put jsonify and do in another module, and import and scan that module, the same thing happens.

I'm sure I'm doing something wrong, but I can't tell what.

import json
import sys

import venusian


def jsonify(wrapped):
    def callback(scanner, name, ob):
        def jsonified(request):
            result = wrapped(request)
            return json.dumps(result)

        scanner.registry.add(name, jsonified)

    venusian.attach(wrapped, callback)
    return wrapped


class Registry:
    def __init__(self):
        self.registered = []

    def add(self, name, ob):
        self.registered.append((name, ob))


@jsonify
def do(x):
    return x

if __name__ == "__main__":
    _registry = Registry()
    _scanner = venusian.Scanner(registry=_registry)

    _current_module = sys.modules[__name__]
    _scanner.scan(_current_module)

    print(_registry.registered)
    # [('do', <function jsonify.<locals>.callback.<locals>.jsonified at 0x7f9844a5d8c8>)]

    print(do({'x': 1}))
    # {'x': 1}

Venusian should work with code using unicode_literals

Hello,

I've been changing some code in one of the applications and I've added

from __future__ import unicode_literals

and ended up with:

  File "/home/ergo/venvs/appenlight/local/lib/python2.7/site-packages/pyramid-1.6.1-py2.7.egg/pyramid/config/__init__.py", line 974, in scan
    ignore=ignore)
  File "/home/ergo/venvs/appenlight/local/lib/python2.7/site-packages/venusian-1.0-py2.7.egg/venusian/__init__.py", line 179, in scan
    invoke(pkg_name, name, ob)
  File "/home/ergo/venvs/appenlight/local/lib/python2.7/site-packages/venusian-1.0-py2.7.egg/venusian/__init__.py", line 137, in invoke
    if _ignore(fullname):
  File "/home/ergo/venvs/appenlight/local/lib/python2.7/site-packages/venusian-1.0-py2.7.egg/venusian/__init__.py", line 129, in _ignore
    if ign(fullname):
TypeError: 'unicode' object is not callable

Shouldn't https://github.com/Pylons/venusian/blob/master/venusian/__init__.py#L117 test for str+unicode instead of just str? Because right now venusian does the wrong thing for unicode string.

Fixup new deprecations coming soon in Python 3.12

tests/test_venusian.py: 35 warnings
  <frozen importlib._bootstrap_external>:572: DeprecationWarning: find_module() is deprecated and slated for removal in Python 3.12; use find_spec() instead

tests/test_venusian.py: 35 warnings
  <frozen importlib._bootstrap_external>:1514: DeprecationWarning: FileFinder.find_loader() is deprecated and slated for removal in Python 3.12; use find_spec() instead

tests/test_venusian.py::TestScanner::test_package_in_zip
  <frozen zipimport>:158: DeprecationWarning: zipimporter.find_module() is deprecated and slated for removal in Python 3.12; use find_spec() instead

tests/test_venusian.py::TestScanner::test_package_in_zip
  <frozen zipimport>:122: DeprecationWarning: zipimporter.find_loader() is deprecated and slated for removal in Python 3.12; use find_spec() instead

Legit new decorators skipped during scan if module imports other decorated things

Since version 1.0a4, methods or classes that contain other methods that might have been scanned will be skipped. Example:

#module foo

@one
def one():
    pass
#module bar
from foo import one

@two
def two():
    one()
    #do something else...

In this example, two won't be scanned, although it might have a completely different function.

Test failure in FrameInfoTest::testCallInfo on Python 3.13

What I did:

  1. Check out current main, 966cce8
  2. Run tox -e py313

What I expect to happen:

All tests pass, as they do for tox -e py312.

What actually happened:

============================================================================================ test session starts ============================================================================================
platform linux -- Python 3.13.0b1, pytest-8.2.0, pluggy-1.5.0
cachedir: .tox/py313/.pytest_cache
rootdir: /home/ben/src/forks/venusian
configfile: setup.cfg
testpaths: tests
plugins: cov-5.0.0
collected 47 items                                                                                                                                                                                          

tests/test_advice.py F..                                                                                                                                                                              [  6%]
tests/test_venusian.py ............................................                                                                                                                                   [100%]

================================================================================================= FAILURES ==================================================================================================
________________________________________________________________________________________ FrameInfoTest.testCallInfo _________________________________________________________________________________________

self = <tests.test_advice.FrameInfoTest testMethod=testCallInfo>

    def testCallInfo(self):
        (kind, module, f_locals, f_globals, codeinfo) = advice.getFrameInfo(
            sys._getframe()
        )
        self.assertEqual(kind, "function call")
>       self.assertTrue(f_locals is locals())  # ???
E       AssertionError: False is not true

tests/test_advice.py:96: AssertionError

----------- coverage: platform linux, python 3.13.0-beta-1 -----------
Name                       Stmts   Miss   Cover   Missing
---------------------------------------------------------
src/venusian/__init__.py     178      0 100.00%
src/venusian/advice.py        24      0 100.00%
src/venusian/compat.py         7      2  71.43%   5-6
---------------------------------------------------------
TOTAL                        209      2  99.04%

========================================================================================== short test summary info ==========================================================================================
FAILED tests/test_advice.py::FrameInfoTest::testCallInfo - AssertionError: False is not true
======================================================================================= 1 failed, 46 passed in 0.21s ========================================================================================

This is related to PEP 667. The frame.f_locals is now a write-through proxy object of type FrameLocalsProxy.

The same issue exists due to the same assertion in zope.interface as zopefoundation/zope.interface#292 and is being worked on in zopefoundation/zope.interface#294.

Venusian should scan superclass for attributes

When decorating methods in a super class and a sub class, venusian will not execute callbacks from a superclass in a subclass. For example:

import venusian

def jsonify(wrapped):
    def callback(scanner, name, ob):
        print wrapped.func_name
    venusian.attach(wrapped, callback)
    return wrapped

class SuperClass(object):
    @jsonify
    def froz_fnord(self): pass

class SubClass(SuperClass):
    @jsonify
    def bar_baz(self): pass

class module(object):
    sub = SubClass() # in this example, this could also be sub = SubClass

venusian.Scanner().scan(module)

My expected output would be:
froz_fnord
bar_baz

The actual output is:
bar_baz

As a workaround, if the scanned module contains an instance of SubClass (as above), the attribute dicts can be merged as follows:

class SubClass(SuperClass):
    @jsonify
    def bar_baz(self): pass

    def __getattribute__(self, name):
        if name == venusian.ATTACH_ATTR:
            def merge_dict_from_superclass(merge_into, merge_from):
                for key, values in merge_from.iteritems():
                    merge_into.setdefault(key, []).extend(values)

            classes = list(self.__class__.__bases__) + [self.__class__]
            attached_attributes = venusian.Categories(None)
            for _class in classes:
                try:
                    more_attributes = object.__getattribute__(_class, venusian.ATTACH_ATTR)
                    merge_dict_from_superclass(attached_attributes, more_attributes)
                except AttributeError:
                    continue
            return attached_attributes
        return object.__getattribute__(self, name)

This produces the desired output.

zipimport.zipimporter.get_filename used for python<2.7

Just put pyramid project on webhoster server using python 2.6.6 (r266:84292, Dec 26 2010, 22:48:11) [GCC 4.4.5]. Since it has almost none of my needed packages, I was putting an egg-collection on the server as well, (containing venusian version: venusian-1.0a7-py2.6). Since I did not want to upload 4000 files, I used compressed eggs

wsgi failed with:

[Wed Jan 30 01:46:20 2013] [error] [client xxx.xxx.xxx.xxx]   File "build/bdist.linux-i686/egg/venusian/__init__.py", line 187, in scan
[Wed Jan 30 01:46:20 2013] [error] [client xxx.xxx.xxx.xxx]     fn = loader.get_filename()
[Wed Jan 30 01:46:20 2013] [error] [client xxx.xxx.xxx.xxx] AttributeError: 'zipimport.zipimporter' object has no attribute 'get_filename'

which is no surprise, since get_filename was introduced in python2.7. It look's like that code is supposed to be for python3.3, but still got executed in 2.6 there.

Update:
Just tried out venusian-1.0a6-py2.6 (since the error producing line is new to a7), I got:

[Wed Jan 30 02:15:54 2013] [error] [client xxx]   File "build/bdist.linux-i686/egg/venusian/__init__.py", line 181, in scan
[Wed Jan 30 02:15:54 2013] [error] [client xxx]     module_type = loader.etc[2]
[Wed Jan 30 02:15:54 2013] [error] [client xxx] AttributeError: 'zipimport.zipimporter' object has no attribute 'etc'

So, the expected attribute etc must be missing. Not sure why, but that's the problem in both cases, I guess.

Update 2:
I was able do get my app running, by putting all eggs not as compressed files, but as directories (since problem was related to zipping, obviously). Still I think, there is something going wrong in venusian there.

Metaclass decoration breaks venusian scope/frame detection mechanism

I am writing a somewhat complex application that uses metaclasses to decorate functions (specifically, add views for a pyramid web application). However, when decorating inside a metaclass, venusian breaks.

From looking at the source, the reason for this seems to be the detection of scope that assumes I must be in a function call (which is correct) and therefore am not decorating a class method (which is incorrect).

I have never worked with venusian before but I tried to figure out the source code anyway. However, at this point I had to give up: I don't exactly understand what's going on here, so I couldn't figure out a fix. Instead, I have created a small testcase that replicates this issue:

import venusian


def test_decorator(wrapped):
    print("Decorated")

    def _callback(context, name, ob):
        print("Callback called")
    venusian.attach(wrapped, _callback)
    return test_decorator


class TestMeta(type):

    def __init__(self, name, bases, attrs):
        self.test = test_decorator(self.test)


class Test:
    __metaclass__ = TestMeta

    #@test_decorator
    def test(self):
        print("test called")

This is, in essence, the problem: The decoration happens during the TestMeta.__init__ method (thus it is a function call) but the method being decorated is at the class scope.

I have tried playing with the depth parameter but I cannot get it to a class level (likely because of the way metaclasses work). If this is not considered a bug, please let me know how to work around it.

Note: You can check the correct way by removing the comment for the decorator above test and commeting out the __metaclass__ attribute instead:

class Test:
    #__metaclass__ = TestMeta

    @test_decorator
    def test(self):
        print("test called")

pip doesn't discover the correct python-requires.

Pip will install the wrong venusian version and later complain the python version is not correct, and error out.
The cause is because in the html on this page: https://pypi.org/simple/venusian/
the anchor tags do not have

data-requires-python=">=3.5"

For example the html of https://pypi.org/simple/pyramid/ has them.

The result is that pip will download the .tar source links, build them, then realise the python_requires is wrong, and crash.

This was not happening yesterday, I have no idea what exactly changed to cause this.

ignore does not quite work as it should...

... I've tried to ignore __main__ but it gets imported (and therefore run) no matter what I do. Venusian should not try to import modules that are being ignored - at all!

AttributeError: 'Scanner' object has no attribute 'test'

I was trying to write a quick little program to test some stuff by doing a simple scan of some of the test modules and for some reason I can't get venusian to work at all. What am I doing wrong?

[marca@marca-mac2 msabramo_test]$ pwd
/Users/marca/dev/git-repos/venusian/msabramo_test
[marca@marca-mac2 msabramo_test]$ pip freeze
gnureadline==6.3.3
ipython==2.4.1
py==1.4.26
pytest==2.6.4
-e [email protected]:Pylons/venusian.git@fe13da4292e154076086e5c026661266e2162977#egg=venusian-master
wheel==0.24.0

[marca@marca-mac2 msabramo_test]$ ipython
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from venusian.tests.fixtures.one import module

In [2]: from venusian import Scanner

In [3]: scanner = Scanner()

In [4]: scanner.scan(module)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-41c39c6e864a> in <module>()
----> 1 scanner.scan(module)

/Users/marca/dev/git-repos/venusian/venusian/__init__.pyc in scan(self, package, categories, onerror, ignore)
    183             # members; walk_packages only iterates over submodules and
    184             # subpackages
--> 185             invoke(pkg_name, name, ob)
    186
    187         if hasattr(package, '__path__'): # package, not module

/Users/marca/dev/git-repos/venusian/venusian/__init__.pyc in invoke(mod_name, name, ob)
    177                         # module but were not actually defined there
    178                         continue
--> 179                     callback(self, name, ob)
    180
    181         for name, ob in getmembers(package):

/Users/marca/dev/git-repos/venusian/venusian/tests/fixtures/__init__.py in callback(context, name, ob)
     11         view_config = self.__dict__.copy()
     12         def callback(context, name, ob):
---> 13             context.test(ob=ob, name=name, **view_config)
     14             self.__class__.call_count += 1
     15         info = venusian.attach(wrapped, callback, category=self.category)

AttributeError: 'Scanner' object has no attribute 'test'

[marca@marca-mac2 msabramo_test]$ cat msabramo_test_scan.py
import sys
import venusian

def test_one():
    scanner = venusian.Scanner()
    print('scanner = %r' % scanner)

    from venusian.tests.fixtures.one import module
    from venusian.tests.fixtures.one import module2
    from venusian.tests.fixtures.two import mod1
    from venusian.tests.fixtures.two import mod2

    scanner.scan(module)
    scanner.scan(module2)
    scanner.scan(mod1)
    scanner.scan(mod2)

    print('venusian.tests.fixtures.decorator.call_count = %r' % venusian.tests.fixtures.decorator.call_count)

[marca@marca-mac2 msabramo_test]$ py.test msabramo_test_scan.py --tb=short --pdb
=================================================================================================================================================== test session starts ====================================================================================================================================================
platform darwin -- Python 2.7.9 -- py-1.4.26 -- pytest-2.6.4
collected 1 items

msabramo_test_scan.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
msabramo_test_scan.py:17: in test_one
    scanner.scan(module)
../venusian/__init__.py:185: in scan
    invoke(pkg_name, name, ob)
../venusian/__init__.py:179: in invoke
    callback(self, name, ob)
../venusian/tests/fixtures/__init__.py:11: in callback
    context.test(ob=ob, name=name, **view_config)
E   AttributeError: 'Scanner' object has no attribute 'test'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /Users/marca/dev/git-repos/venusian/venusian/tests/fixtures/__init__.py(11)callback()
-> context.test(ob=ob, name=name, **view_config)
(Pdb) context
<venusian.Scanner object at 0x103932f90>
(Pdb) name
'Class'
(Pdb) view_config
{'method': True, 'attr': 'method'}

It's 2017, let's get v1.1!

Hey all, it's been a couple years since 1.0 on PyPI, but there's been some decent work here on GitHub. Could someone please do a release of 1.1 (or 1.0.1) with the bugfixes? Thanks!

PyPy tests are broken on PyPy 2.2.1 at least

I tried running 'tox' and the PyPy tests (running my system-installed PyPy 2.2.1) are broken. There seems to be some issue within Nose itself:

...
  File "/home/faassen/projects/venusian-orig/.tox/pypy/site-packages/nose/plugins/manager.py", line 167, in simple
    result = meth(*arg, **kw)
  File "/home/faassen/projects/venusian-orig/.tox/pypy/site-packages/nose_exclude.py", line 144, in wantMethod
    fqn = '%s.%s.%s' % (cls.__module__, cls.__name__, meth.__name__)
AttributeError: 'NoneType' object has no attribute '__module__'

Running the PyPy tests against an older version of Venusian (presumably also using Nose) did not give these errors, however, so it seems some interaction with something within Venusian.

Python 3 tests execute 0 tests

The default tests run against Python 3.2. I don't have that on my system, but when I update tox.ini to use py33, the tests pass, green, but with 0 tests! Tests somehow do not seem to get collected.

Bug reported to Pyramid issue tracker

bug.py:

from pyramid.config import Configurator
import pymongo
db = pymongo.Connection()['test']
config = Configurator()
config.scan()

$ python bug.py
Traceback (most recent call last):
File "bug.py", line 5, in
config.scan()
File "/usr/local/lib/python2.6/dist-packages/pyramid-1.0-py2.6.egg/pyramid/config.py", line 1805, in scan
scanner.scan(package, categories=categories)
File "/usr/local/lib/python2.6/dist-packages/venusian-0.8-py2.6.egg/venusian/init.py", line 55, in scan
invoke(name, ob)
File "/usr/local/lib/python2.6/dist-packages/venusian-0.8-py2.6.egg/venusian/init.py", line 44, in invoke
if not attached_categories.attached_to(ob):
File "/usr/local/lib/python2.6/dist-packages/pymongo-1.11-py2.6-linux-x86_64.egg/pymongo/collection.py", line 1101, in call
self.__name.split(".")[-1])
TypeError: 'Collection' object is not callable. If you meant to call the 'attached_to' method on a 'Collection' object it is failing because no such method exists.

Test failures

Processing dependencies for venusian==1.0a7
Finished processing dependencies for venusian==1.0a7
running tests
running test
running egg_info
writing requirements to venusian.egg-info/requires.txt
writing venusian.egg-info/PKG-INFO
writing top-level names to venusian.egg-info/top_level.txt
writing dependency_links to venusian.egg-info/dependency_links.txt
writing entry points to venusian.egg-info/entry_points.txt
reading manifest file 'venusian.egg-info/SOURCES.txt'
writing manifest file 'venusian.egg-info/SOURCES.txt'
running build_ext
Traceback (most recent call last):
  File "setup.py", line 73, in <module>
    """
  File "/nix/store/wlb2wvnl1r3syz1i6d9ajwdxkk08lrm5-python-offline-distutils-2.7.3/lib/python2.7/site-packages/distutils/core.py", line 152, in setup
    dist.run_commands()
  File "/nix/store/wlb2wvnl1r3syz1i6d9ajwdxkk08lrm5-python-offline-distutils-2.7.3/lib/python2.7/site-packages/distutils/dist.py", line 953, in run_commands
    self.run_command(cmd)
  File "/nix/store/wlb2wvnl1r3syz1i6d9ajwdxkk08lrm5-python-offline-distutils-2.7.3/lib/python2.7/site-packages/distutils/dist.py", line 972, in run_command
    cmd_obj.run()
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 121, in run
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 101, in with_project_on_sys_path
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 130, in run_tests
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/main.py", line 94, in __init__
    self.parseArgs(argv)
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/main.py", line 149, in parseArgs
    self.createTests()
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/main.py", line 158, in createTests
    self.module)
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 128, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 103, in loadTestsFromName
    return self.loadTestsFromModule(obj)
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 34, in loadTestsFromModule
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 103, in loadTestsFromName
    return self.loadTestsFromModule(obj)
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 34, in loadTestsFromModule
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 103, in loadTestsFromName
    return self.loadTestsFromModule(obj)
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 34, in loadTestsFromModule
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 103, in loadTestsFromName
    return self.loadTestsFromModule(obj)
  File "build/bdist.linux-i686/egg/setuptools/command/test.py", line 34, in loadTestsFromModule
  File "/nix/store/kia8w1wryraa4xa6sya5x9ayhjdk64c3-python-2.7.3/lib/python2.7/unittest/loader.py", line 100, in loadTestsFromName
    parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'will_cause_import_error'

Class decorators shadow method decorators.

This bug was not present in 1.0a8. It must have been introduced in 1.0, probably through the work on inheritance? I ran into it because some of my pyramid view configs disappeared from adapter look-up.

When a view class has both a view_config on the class and on a method, the view_config on the method is not processed during scan.

@view_config(name='foo')
class MyView:

    @view_config(name='bar')
    def my_view(self):
        pass

Only foo will be available after the scan, not bar. As a test, I added invalid argument names to the view_config for bar and saw no error during scan. That tells me that the decorator on the method does not get processed at all.

Moving the class decorator to a method fixes this and both decorators get processed.

class MyView:

    @view_config(name='foo')
    def foo_view(self):
        pass

    @view_config(name='bar')
    def my_view(self):
        pass

I hope this information helps to identify and ideally fix the problem quickly. Thank you very much! ;-)

Doctest decorator?

Hi,
I'm trying to test a Pyramid class decorator using Venusian in a simple doctest!
Is there any way with Venusian to scan and "activate" such decorator?

Best regards,
Thierry

view_config doesn't work with config.scan() under Python 3.4

I have try this in __init__.py:

def main():
    config = Configurator()
    config.scan('.views')
    return config.make_wsgi_app()

and the views.py:

@view_config(renderer='string')
def index(request):
    return 'fine'

after serve that, it will got 404 on /.

However, use config.add_view('.views.index', renderer='string') is fine.

pyramid version: 1.5

Why Venusian gives such an exception?

I am writing a simple pyramid application, and I try to run it pserve development.ini.

I got this:

Traceback (most recent call last):
  File "/apps/my/python/packages/.mytest/current/bin/pserve", line 5, in <module>
    sys.exit(pyramid.scripts.pserve.main())
  File "/users/is/pypi/egg_cache/p/pyramid-1.5.1-py2.7.egg/pyramid/scripts/pserve.py", line 51, in main
    return command.run()
  File "/users/is/pypi/egg_cache/p/pyramid-1.5.1-py2.7.egg/pyramid/scripts/pserve.py", line 316, in run
    global_conf=vars)
  File "/users/is/pypi/egg_cache/p/pyramid-1.5.1-py2.7.egg/pyramid/scripts/pserve.py", line 340, in loadapp
    return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/loadwsgi.py", line 247, in loadapp
    return loadobj(APP, uri, name=name, **kw)
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/loadwsgi.py", line 272, in loadobj
    return context.create()
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/loadwsgi.py", line 710, in create
    return self.object_type.invoke(self)
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/loadwsgi.py", line 146, in invoke
    return fix_call(context.object, context.global_conf, **context.local_conf)
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/util.py", line 58, in fix_call
    reraise(*exc_info)
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/compat.py", line 23, in reraise
    exec('raise t, e, tb', dict(t=t, e=e, tb=tb))
  File "/users/is/pypi/egg_cache/p/PasteDeploy-1.5.2-py2.7.egg/paste/deploy/util.py", line 55, in fix_call
    val = callable(*args, **kw)
  File "/users/is/pypi/egg_cache/at/mytest-1.9.0-py2.7.egg//mytest/__init__.py", line 108, in main
  File "/users/is/pypi/egg_cache/p/pyramid-1.5.1-py2.7.egg/pyramid/config/__init__.py", line 930, in scan
    ignore=ignore)
  File "/users/is/pypi/egg_cache/v/venusian-1.0a7-py2.7.egg/venusian/__init__.py", line 187, in scan
    fn = loader.get_filename()
TypeError: zipimporter.get_filename() takes exactly 1 argument (0 given)

Why?

Question about multiple decorators

Hi,
I created two new Python decorators in a Pyramid's project using Venusian to define custom views and add functionalities to them.
I can have several decorators for the same view:

    @page_config(name='myview.html', ...)
    @ajax_config(...)
    class MyViewClass(object):
        """My custon view class"""

My questions are :

  • how can I define decorators order? Actually, whatever order I use, "ajax_config" decorator is always called before "page_config"...
  • to avoid duplicates, is it possible in a decorator to get arguments defined in the previous decorator?

Best regards,
Thierry

Resolve License issue

Hello Team,

At our firm, we scan for licenses to ensure we are compliant. The license in this repo is failing - the link is not opening and also can it be a simpler license like MIT or Apache 2.0.

If it's a complex, or incorrect request, kindly ignore this request.

Thanks,
Sri Harsha

Callback interface is missing the object, key/ name pair under which the decorated method was found

This makes it impossible to distinguish between the decorated object being inserted into an object under two names like this:

@venusion_decorator
def decorated(): pass

class VenusianUser(object):
  foo = decorated
  bar = decorated

My workaround was to use categories and skip some reuse but it would have made my code much easier if I could have gotten the actual object instance and the key under which the decorated object was found on whatever it was found.

views without decorator still venusian'ed

With the code below file2.MyView overrides file1.MyView, even though it has no view_config decorator.

File 1
=====

@view_config(route_name="foo")
class MyView(object):
...


File 2
====
import file1

class MyView(file1.MyView):
    pass

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.