Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions flexx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@

# Assert compatibility
import sys
if sys.version_info < (3, 5): # pragma: no cover
raise RuntimeError('Flexx needs at least Python 3.5')
if sys.version_info < (3, 8): # pragma: no cover
raise RuntimeError('Flexx needs at least Python 3.8')

# Import config object
from ._config import config # noqa
Expand Down
4 changes: 2 additions & 2 deletions flexx/app/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(self, host, port, loop=None, **kwargs):
# Please add comment: What is this used for??
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
if loop is None:
self._loop = asyncio.get_event_loop()
self._loop = _loop.get_or_create_event_loop()
else:
assert isinstance(loop, asyncio.AbstractEventLoop)
self._loop = loop
Expand All @@ -140,7 +140,7 @@ def start(self):
raise RuntimeError('Cannot start a closed or non-serving server!')
if self._running:
raise RuntimeError('Cannot start a running server.')
if asyncio.get_event_loop() is not self._loop:
if _loop.get_or_create_event_loop() is not self._loop:
raise RuntimeError('Can only start server in same thread that created it.')
logger.info('Starting Flexx event loop.')
# Make use of the semi-standard defined by IPython to determine
Expand Down
7 changes: 4 additions & 3 deletions flexx/app/_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ def set_cookie(self, name, value, expires_days=30, version=None,
# Clear cookie?
if value is None:
value = ""
expires = datetime.datetime.utcnow() - datetime.timedelta(days=365)
expires = (datetime.datetime.now(datetime.timezone.utc) -
datetime.timedelta(days=365))
else:
secret = config.cookie_secret
value = create_signed_value(secret, name, value, version=version,
Expand All @@ -296,8 +297,8 @@ def set_cookie(self, name, value, expires_days=30, version=None,
if domain:
morsel["domain"] = domain
if expires_days is not None and not expires:
expires = datetime.datetime.utcnow() + datetime.timedelta(
days=expires_days)
expires = (datetime.datetime.now(datetime.timezone.utc) +
datetime.timedelta(days=expires_days))
if expires:
morsel["expires"] = format_timestamp(expires)
if path:
Expand Down
20 changes: 19 additions & 1 deletion flexx/event/_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ def this_is_js():
return False


def get_or_create_event_loop():
""" Get the current asyncio event loop, creating a new one if needed.

In Python 3.10+ ``asyncio.get_event_loop()`` no longer creates a loop
when none exists, and from Python 3.12 it raises an error in that case.
This helper preserves the historical behavior.
"""
try:
return asyncio.get_running_loop()
except RuntimeError:
try:
return asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop


class Loop:
""" The singleton Flexx event loop at ``flexx.event.loop``. This holds
the queue of pending calls, actions, and reactions. These are queued
Expand Down Expand Up @@ -386,7 +404,7 @@ def integrate(self, loop=None, reset=True):
(though this is currently not tested).
"""
if loop is None:
loop = asyncio.get_event_loop()
loop = get_or_create_event_loop()
with self._lock:
self._thread_id = threading.get_ident()
self._local._active_components = []
Expand Down
3 changes: 2 additions & 1 deletion flexx/event/both_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ def run_in_both(*classes, js=True, py=True, extra_nodejs_args=None):
"""

def wrapper(func):
reference = '\n'.join(line[4:] for line in func.__doc__.splitlines())
reference = '\n'.join(line[4:] if line.startswith(' ') else line
for line in func.__doc__.splitlines())
parts = reference.split('-'*10)
pyref = parts[0].strip(' \n')
jsref = parts[-1].strip(' \n-')
Expand Down
17 changes: 7 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@
import sys
import shutil

try:
import setuptools # noqa, analysis:ignore
except ImportError:
pass # setuptools allows for "develop", but it's not essential

from distutils.core import setup
from setuptools import setup


## Function we need
Expand Down Expand Up @@ -115,7 +110,7 @@ def get_all_resources():
long_description=doc,
platforms='any',
provides=[name],
python_requires='>=3.5',
python_requires='>=3.8',
install_requires=['tornado', 'pscript>=0.7.7', 'webruntime>=0.5.6', 'dialite>=0.5.2'],
packages=package_tree('flexx') + package_tree('flexxamples'),
package_dir={'flexx': 'flexx', 'flexxamples': 'flexxamples'},
Expand All @@ -134,10 +129,12 @@ def get_all_resources():
'Operating System :: POSIX',
'Programming Language :: JavaScript',
'Programming Language :: Python',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
],
)