Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support python 3.10 #2

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
95b61c4
CI: add python 3.9 and 3.10 to test matrix
masipcat Aug 17, 2021
73b48ea
try fix
masipcat Aug 17, 2021
e8802d1
try
masipcat Aug 17, 2021
e78f40d
fix python version
masipcat Aug 17, 2021
cd471ec
upgrade cython and flake8
masipcat Aug 17, 2021
636eeba
fix
masipcat Aug 17, 2021
9873442
ignore F541 + update pycparse
masipcat Aug 17, 2021
a26a047
Flake errors and warnings
masipcat Aug 17, 2021
62d0c38
Update mypy-zope to 0.3.2
masipcat Aug 17, 2021
b02c5d2
exclude cookiecutter
masipcat Aug 17, 2021
7b44c77
mypy
masipcat Aug 17, 2021
ffe0c19
Import Mutablemapping from collections.abc
masipcat Aug 17, 2021
cd4fa89
mypy
masipcat Aug 17, 2021
acd1ef3
CI: run mypy before tests in the same environment
masipcat Aug 17, 2021
f7735b4
flake: exclude cookiecutter
masipcat Aug 17, 2021
7f8fe39
cffi
masipcat Aug 17, 2021
06e7c84
fix
masipcat Aug 17, 2021
8e81529
requirements
masipcat Aug 20, 2021
7ab4068
aioredis 2.0 and other fixes
masipcat Aug 20, 2021
9ed56a7
fix
masipcat Aug 20, 2021
945f004
Fixes
masipcat Sep 8, 2021
ca7dfc8
fix
masipcat Sep 10, 2021
b398f78
fix
masipcat Sep 10, 2021
29b0bca
aioredis mypy ignore-imports
masipcat Sep 10, 2021
acfae52
Changelog
masipcat Sep 10, 2021
4aa11eb
Forgot to update aioredis=2.0.0 in requirements
masipcat Sep 10, 2021
b2e10a8
Reenable all python versions
masipcat Sep 10, 2021
1c31b74
Merge branch 'master' into support-python-3.10
masipcat Sep 10, 2021
148cd02
Use custom implementation of ContextVar that is not copied automatica…
masipcat Sep 13, 2021
d395e27
Merge branch 'master' into support-python-3.10
masipcat Sep 13, 2021
6fca665
Update utility.py
masipcat Sep 13, 2021
52ef78d
Update utility.py
masipcat Sep 13, 2021
01066c3
Fix
masipcat Sep 13, 2021
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
19 changes: 9 additions & 10 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,23 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8]
python-version: [3.7, 3.8, 3.9, 3.10.0-rc.1]

steps:
- name: Checkout the repository
uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install package
run: |
pip install flake8==3.7.7
pip install mypy==0.720
pip install mypy-zope==0.2.0
pip install black==19.10b0
pip install isort==4.3.21
pip install $(grep -P 'flake8|black|isort' contrib-requirements.txt)
- name: Run pre-checks
run: |
flake8 guillotina --config=setup.cfg
mypy guillotina/ --ignore-missing-imports
isort -c -rc guillotina/
black --check --verbose guillotina
# Job to run tests
Expand All @@ -39,7 +34,7 @@ jobs:

strategy:
matrix:
python-version: [3.7, 3.8]
python-version: [3.7, 3.8, 3.9, 3.10.0-rc.1]
database: ["DUMMY", "postgres", "cockroachdb"]
db_schema: ["custom", "public"]
exclude:
Expand All @@ -59,7 +54,7 @@ jobs:
uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

Expand All @@ -74,6 +69,10 @@ jobs:
- name: Start memcached image
uses: niden/actions-memcached@v7

- name: Check mypy
run: |
mypy guillotina/

- name: Run tests
run: |
pytest -rfE --reruns 2 --cov=guillotina -s --tb=native -v --cov-report xml --cov-append guillotina
Expand Down
13 changes: 10 additions & 3 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
CHANGELOG
=========

6.3.16 (unreleased)
6.4.0 (unreleased)
-------------------

- Add support for Python 3.10
[masipcat]
- Reimplemented IRedisUtility to adapt to aioredis v2.0 breaking changes
[masipcat]
- Upgraded dev dependencies
[masipcat]
- Use custom implementation of ContextVar that is not copied automatically to new tasks
[masipcat]
- Fix vocabulray country code AN


6.3.15 (2021-08-05)
-------------------

- fix: Add MIMEMultipart('alternative') to attach message in parent MIMEMultipart to render only html body.
- fix: Add MIMEMultipart('alternative') to attach message in parent MIMEMultipart to render only html body.
[rboixaderg]

6.3.14 (2021-08-04)
Expand Down
13 changes: 6 additions & 7 deletions contrib-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
aioredis==1.3.1
aioredis==2.0.0
html2text==2019.8.11
aiosmtplib==1.1.4
pre-commit==1.18.2
flake8==3.7.7
flake8==3.9.2
codecov==2.0.15
mypy==0.720
mypy-zope==0.2.0
mypy-zope==0.3.2
black==19.10b0
isort==4.3.21
jinja2==2.11.3
pytz==2020.1
emcache==0.4.1
pymemcache==3.4.0
pillow==8.2.0
emcache==0.4.1; python_version < '3.10'
pymemcache==3.4.0; python_version < '3.10'
pillow==8.3.2
2 changes: 1 addition & 1 deletion guillotina/api/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ async def __call__(self):

jwt_token = jwt.encode(
data, app_settings["jwt"]["secret"], algorithm=app_settings["jwt"]["algorithm"]
).decode("utf-8")
)

await notify(UserRefreshToken(user, jwt_token))

Expand Down
6 changes: 1 addition & 5 deletions guillotina/async_util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from dateutil.tz import tzutc
from guillotina import logger
from guillotina import task_vars
from guillotina.db.transaction import Status
Expand All @@ -18,9 +17,6 @@
import typing


_zone = tzutc()


class QueueUtility(object):
def __init__(self, settings=None, loop=None):
self._queue = None
Expand All @@ -31,7 +27,7 @@ def __init__(self, settings=None, loop=None):
@property
def queue(self):
if self._queue is None:
self._queue = asyncio.Queue(loop=self._loop)
self._queue = asyncio.Queue()
return self._queue

async def initialize(self, app=None):
Expand Down
4 changes: 1 addition & 3 deletions guillotina/auth/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,5 @@ def authenticate_user(userid, data=None, timeout=60 * 60 * 1):
"sub": userid,
}
)
jwt_token = jwt.encode(
data, app_settings["jwt"]["secret"], algorithm=app_settings["jwt"]["algorithm"]
).decode("utf-8")
jwt_token = jwt.encode(data, app_settings["jwt"]["secret"], algorithm=app_settings["jwt"]["algorithm"])
return jwt_token, data
2 changes: 1 addition & 1 deletion guillotina/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ async def cleanup(self, app):
await app.shutdown()
except Exception:
logger.warning("Unhandled error cleanup tasks", exc_info=True)
for task in asyncio.Task.all_tasks():
for task in asyncio.all_tasks():
if task.done():
continue
if "cleanup" in task._coro.__qualname__:
Expand Down
2 changes: 1 addition & 1 deletion guillotina/component/globalregistry.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def __init__(self, parent, name):


@implementer(IComponentLookup)
class GlobalComponents(Components):
class GlobalComponents(Components): # type: ignore
def _init_registries(self):
self.adapters = GuillotinaAdapterRegistry(self, "adapters")
self.utilities = GuillotinaAdapterRegistry(self, "utilities")
Expand Down
2 changes: 1 addition & 1 deletion guillotina/configure/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def __init__(self, etype, evalue):
self.etype, self.evalue = etype, evalue

def __str__(self): # pragma NO COVER
return "%s: %s\n in:\n %s" % (self.etype, self.evalue)
return "%s: %s" % (self.etype, self.evalue)


##############################################################################
Expand Down
3 changes: 2 additions & 1 deletion guillotina/contrib/cache/strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from guillotina.exceptions import NoPubSubUtility
from guillotina.interfaces import ICacheUtility
from guillotina.profile import profilable
from guillotina.task_vars import copy_context
from typing import Any
from typing import Dict
from typing import List
Expand Down Expand Up @@ -129,7 +130,7 @@ async def close(self, invalidate=True, publish=True):
await self.fill_cache()
if len(self._keys_to_publish) > 0 and self._utility._subscriber is not None:
keys = self._keys_to_publish
asyncio.ensure_future(self.synchronize(keys))
asyncio.ensure_future(copy_context(self.synchronize(keys)))
else:
self._stored_objects.clear()
else:
Expand Down
7 changes: 4 additions & 3 deletions guillotina/contrib/mailer/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from guillotina.contrib.mailer.exceptions import NoEndpointDefinedException
from guillotina.interfaces import IMailEndpoint
from guillotina.interfaces import IMailer
from guillotina.task_vars import copy_context
from guillotina.utils import get_random_string
from zope.interface import implementer

Expand Down Expand Up @@ -135,7 +136,7 @@ def get_endpoint(self, endpoint_name):
else:
raise NoEndpointDefinedException("{} mail endpoint not defined".format(endpoint_name))
utility.from_settings(settings)
asyncio.ensure_future(utility.initialize())
asyncio.ensure_future(copy_context(utility.initialize()))
self._endpoints[endpoint_name] = utility
return self._endpoints[endpoint_name]

Expand Down Expand Up @@ -223,7 +224,7 @@ async def finalize(self):
@implementer(IMailer)
class PrintingMailerUtility(MailerUtility):
def __init__(self, settings=None, loop=None):
self._queue = asyncio.Queue(loop=loop)
self._queue = asyncio.Queue()
self._settings = settings or {}

async def _send(self, sender, recipients, message, endpoint_name="default"):
Expand All @@ -233,7 +234,7 @@ async def _send(self, sender, recipients, message, endpoint_name="default"):
@implementer(IMailer)
class TestMailerUtility(MailerUtility):
def __init__(self, settings=None, loop=None):
self._queue = asyncio.Queue(loop=loop)
self._queue = asyncio.Queue()
self.mail = []

async def send(
Expand Down
12 changes: 8 additions & 4 deletions guillotina/contrib/pubsub/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,9 @@ async def finalize(self, app):
self._initialized = False
await asyncio.sleep(0.1)

async def real_subscribe(self, channel_name):
async def real_subscribe(self, channel, channel_name):
while channel_name in self._subscribers:
try:
channel = await self._driver.subscribe(channel_name)
async for msg in channel:
try:
try:
Expand All @@ -76,10 +75,14 @@ async def real_subscribe(self, channel_name):
return
except Exception:
logger.error(f"Unhandled exception with pubsub. Sleeping before trying again", exc_info=True)
# TODO: maybe we should call the callback with a disconnected event or do it on reconnect,
# so the callback has a chance to perform the logic to recover.
await asyncio.sleep(1)
finally:
try:
# Restart subscription
await self._driver.unsubscribe(channel_name)
channel = await self._driver.subscribe(channel_name)
except Exception:
pass

Expand All @@ -90,8 +93,9 @@ async def subscribe(self, channel_name: str, rid: str, callback: Callable[[str],
self._subscribers[channel_name][rid] = callback
else:
self._subscribers[channel_name] = {rid: callback}
task = asyncio.ensure_future(self.real_subscribe(channel_name))
self._tasks[channel_name] = task
# Moved the subscribe command outside the future to ensure we are subscribed after returning
channel = await self._driver.subscribe(channel_name)
self._tasks[channel_name] = asyncio.ensure_future(self.real_subscribe(channel, channel_name))

async def unsubscribe(self, channel_name: str, req_id: str):
if self._driver is None:
Expand Down
Loading