Git Product home page Git Product logo

pyee's Introduction

pyee's People

Contributors

asellappen avatar blshkv avatar dependabot[bot] avatar doboy avatar fabaff avatar forslund avatar jfhbrook avatar livinthelookingglass avatar massongit avatar mxschmitt avatar niklasf avatar polyzen avatar thedjinn avatar timgates42 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  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  avatar  avatar

pyee's Issues

refactor EE import paths

Instead of from pyee import EventEmitter, TwistedEventEmitter etc, consider:

from pyee import EventEmitter  # alias
from pyee.base import EventEmitter
from pyee.twisted import TwistedEventEmitter

The current aliases would work as they do now but be marked as deprecated, similar to the BaseEventEmitter.

A nitpick and an a couple of inconsistency with node's EventEmitter

  1. Event_emitter should really be named EventEmitter according to PEP 8
  2. ee.emit('data') when there is no callback attached to the event data should return False instead of throwing an error.
  3. Errors should be handle through emission of error e.on('error')
$ node
> e = new (require('events').EventEmitter)()
{}
> e.emit('data')
false
> e.on('data', function(){})
> e.emit('data')
true
> e.emit('error')
Error: Uncaught, unspecific 'error' event.
$ python
>>> e = Event_emitter()
>>> e.emit('data')
KeyError: 'data'

I am not sure which of these you feel strongly for/against, so I am just putting it on the table before implementing anything

Recommend error handling

Current error handling

    def _emit_run(self, f, args, kwargs):
        try:
            coro = f(*args, **kwargs)
        except Exception as exc:
            self.emit("error", exc)

recommend to include the function name/args/kwargs etc to help with debugging

    def _emit_run(self, f, args, kwargs):
        try:
            coro = f(*args, **kwargs)
        except Exception as exc:
            self.emit("error", exc, f, args, kwargs)

or some such thing

**kw

Maybe add **kw named arguments in addition to *args for events?

Handle for the async functions?

Hi. This code do nothing:

from pyee import AsyncIOEventEmitter
ee = AsyncIOEventEmitter()

@ee.on('ready')
async def ready():
        print('ready')

if __name__ == '__main__':
        ee.emit('ready')

What can I do?

generate API docs

Should generate API docs from my docstrings. Can use a custom script, or can just bite the bullet and readthedocs.

[Regression]: EventEmitter.listeners("foo") throws if no listener exists

The following:

from pyee import EventEmitter
ee = EventEmitter()
ee.listeners("foo")

results in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../env/lib/python3.10/site-packages/pyee/base.py", line 229, in listeners
    return list(self._events[event].keys())
KeyError: 'foo'
>>> 

since version 9.0.0. In version <8 it was returning an empty list instead. This most likely broke in #99 when the defaultdict of EventEmitter._events got changed to a normal dict.

All callbacks to the same event must take similar signature

This is somewhat of an inconvinience. Obviously this is due to python being stricter about function signatures than javascript is.

Take the following example:

from pyee import EventEmitter

def takes_one(arg1):
    print(arg1)

def takes_two(arg1, arg2):
    print(arg1, arg2)

ee = EventEmitter()

ee.on('a', takes_one)
ee.on('a', takes_two)

ee.emit('a', 'something', 'another')

This would be fine in javascript but results in a TypeError in python.

For me the most convenient would be that extra arguments was simply dropped when calling functions that takes fewer arguments.

The other case where you expect more arguments than is emitted is not as relevant, as you should know the number of possible arguments that an event can emit.

Or we could just live with it and require identical signatures?

"port of Node.js EventEmitter" not entirely accurate

I stopped tracking Node.js features ages ago and a lot of the features of this library aren't inspired by Node at all.

You could say this is a "loose port" or that it's "inspired by" Node's EE.

Task: Land on copy I like and update the following:

  • README description
  • Descriptions in docstrings
  • Descriptions in docs
  • Github description
  • jfhbrook/public repo

Handle possible race condition when using ExecutorEventEmitter

We've had an error report in Mycroft with an exception when removing a once handler.

Been trying to reproduce and I think it's a race condition. We have a sequence which sets up a once listener waits for 5 seconds for the listener to be called. If the handler is called it returns immediately if the 5 seconds passes without the handler being triggered the listener is removed.

Sometimes (quite rarely) the handler gets called, 5 seconds times out and removes the listener. THEN the once wrapper tries to remove the listener.

A try/except block may be a simple solution to remove the exception log

def _wrapper(f):
            def g(*args, **kwargs):
                try:
                    self.remove_listener(event, f)
                except KeyError:
                    # log warning or something
                    pass  # or possibly return

                # f may return a coroutine, so we need to return that
                # result here so that emit can schedule it
                return f(*args, **kwargs)

            self._add_event_handler(event, f, g)

A proper solution would be to have a lock around the critical section(s)

Support for asynchronous methods.

Have you considered supporting asynchronous functions as handlers or even creating an asynchronous emit function ?

This would only be supported in 3.4+, but in my use case is a must. If you're interested I could elaborate a bit more on the requirements.

I'd be available to work with you on this, never breaking backwards compatibility but making such methods available for 3.4+ adopters.

WDYT?

once can't remove handler

Do not work removing handler from event after call

>>> from pyee import Event_emitter
>>> ee = Event_emitter()
>>> @ee.once('event1')
def e1_handler():
    print 'Event 1'

>>> ee.emit('event1')
Event 1
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    ee.emit('event1')
  File "/home/quard/src/pyee/pyee/__init__.py", line 37, in emit
    fxn(*args)
  File "/home/quard/src/pyee/pyee/__init__.py", line 43, in g
    self.remove(self,event)
AttributeError: 'Event_emitter' object has no attribute 'remove'

Trio support

Hey, thanks for this awesome looking library. I'm investigate the feasibility of using it on one of my projects and I see that pyee supports asyncio and twisted for async capabilities. I am wondering if there is any motivation to also support the trio library:

https://trio.readthedocs.io/

I'm relying on the trio async streams implementation and I'd also like to be able to plug on this event emitter class onto my stream. What do you think?

Fix PPC builds

Someone contributed a patch to enable tests against PPC on Travis. I migrated the primary CI suite to GitHub Actions but they don't test PPC.

I could continue testing PPC on Travis; however, travisci.com refuses to show me the pyee repo as one I can enable it for. I suspect it broke in the .org -> .com migration but I don't know for sure.

The scope of this ticket is to either find an alternate platform for testing PPC, or to get Travis working so I can continue using it to test PPC. The Travis yaml config is still there and will probably Just Work once the access issue is sorted.

This is low priority because pyee doesn't have any native deps and therefore doesn't have any PPC-specific issues - but it's lost functionalty.

asyncio done callback is also called for cancelled events

pyee registers a 'done' callback to asyncio tasks / futures, which retrieves any exceptions to emit:

pyee/pyee/_asyncio.py

Lines 55 to 59 in 8cab87d

@f.add_done_callback
def _callback(f):
exc = f.exception()
if exc:
self.emit('error', exc)

However, if the task / future is cancelled, then calling .exception() will raise asyncio.CancelledError, see the asyncio.Task.exception() documentation:

If the Task has been cancelled, this method raises a CancelledError exception.

During a normal shutdown, I see a lot of these:

Traceback (most recent call last):
    ...
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
    self._context.run(self._callback, *self._args)
  File "/.../site-packages/pyee/_compat.py", line 60, in _callback
    exc = f.exception()
asyncio.exceptions.CancelledError

(this is via a 3rd-party project that uses pyee and hasn't switched yet AsyncIOEventEmitter, but the principle is the same).

In my own callback handlers, I always check first if the task has been cancelled, and further ignore KeyboardInterrupt and SystemExit:

def foobar_sample_handler(task: asyncio.Task[Any]) -> None:
    if task.cancelled():
        return
    exception = task.exception()
    if exception is None or isinstance(exception, (KeyboardInterrupt, SystemExit)):
        return
    # ... do stuff with exception.

Does pyee really need to propagate KeyboardInterrupt and SystemExit, as well? It definitely should not trip up on cancelled tasks, however.

At least one test is broken.

The test for ee.once did not fail for issue #1. Tests should fail when things are broken, so this test needs to be troubleshot. Other similar tests might also be effected.

Automate RTD Build

The RTD build doesn't seem to run automatically. I have to go in there and hit the button every time. I don't like having to fiddle with it every release, so it would be worth digging into what's going on.

I thought RTD used a webhook - is that true? Is that even configured? Or maybe there's a GitHub Action I need to look at? All things I don't know, but things I'd like to sort out someday.

Adopt pyproject.toml

I think it's about time that pyee adopt pyproject.toml. It already has a file for configuring isort and pyright, but a lot of fields can be actively moved there from setup.py.

Note, I should retain a setup.py for compatibility purposes; I shouldn't do away with it completely! But if I can move the package name/version into the toml file, that could enable automating the version bump in the sphinx docs.

Emit can be error

Sorry for my english..

from pyee import EventEmitter

ee = EventEmitter()

ee.emit('error')

It will be "Uncaught, unspecified 'error' event."
But - ee.emit('esadasdsadsa') wont

check for event = error, but instead of error there will be a generated hash with a key, or can it somehow be done differently?

Or it's okay?

Async test for v2.7

I read from Travis:

  • 11 tests passed on 2.7
  • 15 tests passed on 3.0.3

Does it mean v2.7 is half supported? Do you have ideas how to test events asynchronously with 2.7?

Thanks!

Celery and RQ support

6.0.0 has a way of supporting fairly arbitrary backends. That means that we could make an event emitter that can hook onto a celery app. Maybe like:

from celery import Celery
from pyee import CeleryEventEmitter

app = Celery('events', broker='pyamqp://guest@localhost//')

# Creates a unique @app.task that gets emit task calls for this
# EE from celery and executes standard emit behavior
ee = CeleryEventEmitter(app=app)

# Register handlers like normal
@ee.on('data')
def handler(data):
    print(data)

then you can spin up workers like normal:

celery -A example_app worker --loglevel=info

and emit from your main program:

from example_app import ee

# Calls our generated celery task with the payload;'
# actual emit code happens on servers
ee.emit('data', dict(some='data'))

See: http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html#application

[question] recommended documentation method

Hi!

First of all thanks for pyee and for making it asyncio-friendly with support for coroutines!

I am using pyee for aiortc, my Python/asyncio implementation of WebRTC . I was wondering whether you have a recommendation on how to document the events an object can emit?

test_async.py failure

In test_asyncio_cancellation, I get asyncio.exceptions.TimeoutError instead of concurrent.futures.TimeoutError. Thus:

Index: pyee-7.0.1/tests/test_async.py
===================================================================
--- pyee-7.0.1.orig/tests/test_async.py	2020-01-30 21:22:49.000000000 +0100
+++ pyee-7.0.1/tests/test_async.py	2020-03-27 10:10:34.734403451 +0100
@@ -4,7 +4,7 @@ import pytest
 import pytest_asyncio.plugin  # noqa
 
 from asyncio import Future, wait_for
-from concurrent.futures import TimeoutError
+from asyncio.exceptions import TimeoutError
 from mock import Mock
 
 from twisted.internet.defer import ensureDeferred, succeed``

helps, however I am not sure about a general solution.

Possible to use @ee.on() decorator on class method?

I think the answer to this is No, but wanted to check and see:

I have a class with:

    async init(self):
        ee.on(ActionList.A_DOWNLOAD, self.handle_action_A_DOWNLOAD)
        # ...

    async def handle_action_A_DOWNLOAD(self, event: Event):
        #blah blah

Is there any way to decorate the task directly?

    async init(self):
        # ...

    @ee.on(ActionList.A_DOWNLOAD)
    async def handle_action_A_DOWNLOAD(self, event: Event):
        #blah blah

In my other module, I'm emitting as follows:

msg = DownloadMessage(...)
ee.emit(ActionList.A_DOWNLOAD, msg)

Interestingly, when I use the decorator as above the self argument is my other module, and the msg parameter is missing

Events & subevents

Maybe make the event name a tuple instead of a string, and run handlers registered with a prefix of a fired event tuple.

Example:

@ee.on(('login', 'web', 'openid'))
def foo(_arg, *_kw):
print "Logged in using openid"

@ee.on(('login',))
def foo(_arg, *_kw):
print "Logged in"

ee.emit(('login', 'web', 'openid', 'http://google.com')
Logged in using openid
Logged in

Using in Multiple Scripts

How do I use this event emitter in multiple scripts?

In NodeJS, I can export the event in one script, and subscribe to a channel in another script after importing the same channel.

How do I so the same with Pyee in Python? Any code suggestions will be appreciated.

Wrap captured exceptions in a PyeeError

In #94 we noted that when an error is captured in the AsyncIOEventEmitter, it can be tough to debug due to losing the context in which the handler was called.

One way to address this may be to create a wrapper exception type which includes the event name, args and kwargs the event handler was called with. This is, as far as I know, not something Node.js does, and it's a real weakness with the abstraction! But this approach is somewhat similar to twisted's Failures and pyee will sometimes raise PyeeExceptions today so it's not too much of a stretch.

I've been wanting to rename PyeeException to PyeeError for some time, and this seems like a good opportunity to introduce that interface by inheriting from PyeeException and adding contextually meaningful metadata to error subclasses.

pyee release 9.0.x

  • merge #97
  • dust off + merge #84
  • make changes to + merge #96
  • test in copr and make naive fixes - it fails due to not knowing to install build dependencies, fixing that is out of scope for this release
  • keep testing in copr + patch (punting on working build)
  • update changelog
  • tag/push release
  • publish to pypi
  • ensure rtd build succeeded
  • dev.to post on release

once listeners arn't awaited

I have a listener that's a coroutine, and it's a once event. However, it isn't awaited, hence it doesn't run.

Clean up docstrings

I think they're inaccurate, and the top level docstring can be much more terse.

OSX Issue module 'select' has no attribute 'epoll'

app_1            | Traceback (most recent call last):
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
app_1            |     worker.init_process()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/workers/ggevent.py", line 146, in init_process
app_1            |     super().init_process()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/workers/base.py", line 134, in init_process
app_1            |     self.load_wsgi()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
app_1            |     self.wsgi = self.app.wsgi()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/app/base.py", line 67, in wsgi
app_1            |     self.callable = self.load()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
app_1            |     return self.load_wsgiapp()
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
app_1            |     return util.import_app(self.app_uri)
app_1            |   File "/usr/local/lib/python3.9/site-packages/gunicorn/util.py", line 359, in import_app
app_1            |     mod = importlib.import_module(module)
app_1            |   File "/usr/local/lib/python3.9/importlib/__init__.py", line 127, in import_module
app_1            |     return _bootstrap._gcd_import(name[level:], package, level)
app_1            |   File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
app_1            |   File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
app_1            |   File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
app_1            |   File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
app_1            |   File "<frozen importlib._bootstrap_external>", line 790, in exec_module
app_1            |   File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
app_1            |   File "/usr/src/app/ruckit/wsgi.py", line 17, in <module>
app_1            |     application = Cling(get_wsgi_application())
app_1            |   File "/usr/local/lib/python3.9/site-packages/django/core/wsgi.py", line 12, in get_wsgi_application
app_1            |     django.setup(set_prefix=False)
app_1            |   File "/usr/local/lib/python3.9/site-packages/django/__init__.py", line 24, in setup
app_1            |     apps.populate(settings.INSTALLED_APPS)
app_1            |   File "/usr/local/lib/python3.9/site-packages/django/apps/registry.py", line 114, in populate
app_1            |     app_config.import_models()
app_1            |   File "/usr/local/lib/python3.9/site-packages/django/apps/config.py", line 211, in import_models
app_1            |     self.models_module = import_module(models_module_name)
app_1            |   File "/usr/local/lib/python3.9/importlib/__init__.py", line 127, in import_module
app_1            |     return _bootstrap._gcd_import(name[level:], package, level)
app_1            |   File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
app_1            |   File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
app_1            |   File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
app_1            |   File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
app_1            |   File "<frozen importlib._bootstrap_external>", line 790, in exec_module
app_1            |   File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
app_1            |   File "/usr/src/app/ruckit/billing/models.py", line 26, in <module>
app_1            |     from ruckit import email as ruckit_email, pdf as ruckit_pdf
app_1            |   File "/usr/src/app/ruckit/pdf.py", line 3, in <module>
app_1            |     from pyppeteer import launch, errors
app_1            |   File "/usr/local/lib/python3.9/site-packages/pyppeteer/__init__.py", line 30, in <module>
app_1            |     from pyppeteer.launcher import connect, launch, executablePath  # noqa: E402
app_1            |   File "/usr/local/lib/python3.9/site-packages/pyppeteer/launcher.py", line 25, in <module>
app_1            |     from pyppeteer.browser import Browser
app_1            |   File "/usr/local/lib/python3.9/site-packages/pyppeteer/browser.py", line 11, in <module>
app_1            |     from pyee import EventEmitter
app_1            |   File "/usr/local/lib/python3.9/site-packages/pyee/__init__.py", line 59, in <module>
app_1            |     from pyee._trio import TrioEventEmitter  # noqa
app_1            |   File "/usr/local/lib/python3.9/site-packages/pyee/_trio.py", line 4, in <module>
app_1            |     import trio
app_1            |   File "/usr/local/lib/python3.9/site-packages/trio/__init__.py", line 18, in <module>
app_1            |     from ._core import (
app_1            |   File "/usr/local/lib/python3.9/site-packages/trio/_core/__init__.py", line 29, in <module>
app_1            |     from ._run import (
app_1            |   File "/usr/local/lib/python3.9/site-packages/trio/_core/_run.py", line 2370, in <module>
app_1            |     from ._io_epoll import EpollIOManager as TheIOManager
app_1            |   File "/usr/local/lib/python3.9/site-packages/trio/_core/_io_epoll.py", line 188, in <module>
app_1            |     class EpollIOManager:
app_1            |   File "/usr/local/lib/python3.9/site-packages/trio/_core/_io_epoll.py", line 189, in EpollIOManager
app_1            |     _epoll = attr.ib(factory=select.epoll)
app_1            | AttributeError: module 'select' has no attribute 'epoll'

This has worked previously but has suddenly stopped working.

I tried updating to the latest versions however, no luck.

pyppeteer==0.2.6
pyee==8.1.0

broken setup.py

That's probably related to #73 which you failed to merge probably, but I don't remember for sure.

 * pyee-8.1.0.tar.gz BLAKE2B SHA512 size ;-) ...                                               [ ok ]
>>> Unpacking source...
>>> Unpacking pyee-8.1.0.tar.gz to /var/tmp/portage/dev-python/pyee-8.1.0/work
>>> Source unpacked in /var/tmp/portage/dev-python/pyee-8.1.0/work
>>> Preparing source in /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0 ...
 * Applying setup-8.0.1.patch ...                                                              [ ok ]
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0 ...
>>> Source configured.
>>> Compiling source in /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0 ...
 * python3_8: running distutils-r1_run_phase distutils-r1_python_compile
python3.8 setup.py build -j 4
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
running build
running build_py
creating /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/uplift.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_twisted.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_trio.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_executor.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_compat.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_base.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/_asyncio.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
copying pyee/__init__.py -> /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee
running egg_info
writing pyee.egg-info/PKG-INFO
writing dependency_links to pyee.egg-info/dependency_links.txt
writing top-level names to pyee.egg-info/top_level.txt
reading manifest file 'pyee.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'pyee.egg-info/SOURCES.txt'
/usr/lib/python3.8/distutils/dist.py:274: UserWarning: Unknown distribution option: 'vcversioner'
  warnings.warn(msg)
warning: build_py: byte-compiling is disabled, skipping.

>>> Source compiled.
>>> Test phase [not enabled]: dev-python/pyee-8.1.0

>>> Install dev-python/pyee-8.1.0 into /var/tmp/portage/dev-python/pyee-8.1.0/image
 * python3_8: running distutils-r1_run_phase distutils-r1_python_install
python3.8 setup.py install --skip-build --root=/var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
WARNING: The pip package is not available, falling back to EasyInstall for handling setup_requires/test_requires; this is deprecated and will be removed in a future version.
running install
running install_lib
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages
creating /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/__init__.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_asyncio.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_base.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_compat.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_executor.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_trio.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/_twisted.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
copying /var/tmp/portage/dev-python/pyee-8.1.0/work/pyee-8.1.0-python3_8/lib/pyee/uplift.py -> /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/__init__.py to __init__.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_asyncio.py to _asyncio.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_base.py to _base.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_compat.py to _compat.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_executor.py to _executor.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_trio.py to _trio.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/_twisted.py to _twisted.cpython-38.pyc
byte-compiling /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee/uplift.py to uplift.cpython-38.pyc
writing byte-compilation script '/var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpu1i22n7b.py'
/usr/bin/python3.8 /var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpu1i22n7b.py
removing /var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpu1i22n7b.py
writing byte-compilation script '/var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpz7hslbq1.py'
/usr/bin/python3.8 /var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpz7hslbq1.py
removing /var/tmp/portage/dev-python/pyee-8.1.0/temp/tmpz7hslbq1.py
running install_egg_info
running egg_info
writing pyee.egg-info/PKG-INFO
writing dependency_links to pyee.egg-info/dependency_links.txt
writing top-level names to pyee.egg-info/top_level.txt
reading manifest file 'pyee.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'pyee.egg-info/SOURCES.txt'
Copying pyee.egg-info to /var/tmp/portage/dev-python/pyee-8.1.0/image/_python3.8/usr/lib/python3.8/site-packages/pyee-0.0.0-py3.8.egg-info
running install_scripts
/usr/lib/python3.8/distutils/dist.py:274: UserWarning: Unknown distribution option: 'vcversioner'
  warnings.warn(msg)
 * Using python3.8 in global scope
 * python3_8: running distutils-r1_run_phase distutils-r1_python_install_all
>>> Completed installing dev-python/pyee-8.1.0 into /var/tmp/portage/dev-python/pyee-8.1.0/image

upgrade(subcls, underlying)

This would generate an instance of subcls that attaches wrappers for all of underlying's current listeners. After the "upgrade", all changes to the returned instance will not be proxied to underlying.

This would be handy if someone generated a BaseEventEmitter with certain events already defined, but you know that you're working in a different environment and want to use a subclass.

adding an emit_async() to AsyncIOEventEmitter

Everything would remain the same with emit(), but it would await any coroutines. My use case is that I need to know when all the registered coroutines are finished. Does it make sense to add it?

revamp packaging

I switched to setuptools. Need to:

[ ] Read setuptools docs, figure out which strings I don't need (can probably ditch long_description)
[ ] Make supported python versions backed up by tox
[ ] ????

ProxyEventEmitter

This would be a class ProxyEventEmitter(underlying) that by default proxies all methods to the underlying event emitter and allows for overwriting self.underlying with a getter. This will be helpful for #49 since the suggested classes need this functionality.

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.