From a145a823fb83194e687d6f0d6f4c758186119136 Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:39:52 +0200 Subject: [PATCH 1/7] [MQ-683] Updated requirements. --- requirements-dev.txt | 2 +- requirements.txt | 15 +++++------ setup.py | 59 +++++++++++++------------------------------- 3 files changed, 26 insertions(+), 50 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index bade6b9..1e883f1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,4 +3,4 @@ Sphinx==1.3.3 Sphinx-PyPI-upload==0.2.1 twine==1.6.4 sphinxcontrib-dashbuilder==0.1.0 -rst2pdf==0.93 +rst2pdf==0.98 diff --git a/requirements.txt b/requirements.txt index 7a314e6..cd00c84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ -Django>=1.7 -gevent==1.0.2 ; platform_python_implementation == "CPython" and python_version < "3.0" -gevent==1.1rc2 ; platform_python_implementation != "CPython" or python_version >= "3.0" -gevent-websocket==0.9.5 -psycopg2==2.6.1 ; platform_python_implementation == "CPython" -psycopg2cffi>=2.7.2 ; platform_python_implementation != "CPython" -six==1.10.0 +Django==1.11.29 +meteor-ejson==1.1.0 +psycogreen==1.0.2 +pybars3==0.9.7 +six==1.15.0 +gevent==21.1.2 +psycopg2==2.8.6 +git+https://github.com/MEERQAT/gevent-websocket.git@v0.11.0#egg=gevent-websocket diff --git a/setup.py b/setup.py index 78a7f99..fad1bc1 100644 --- a/setup.py +++ b/setup.py @@ -14,12 +14,10 @@ import setuptools.command.build_ext # pypi import setuptools -# setuptools 18.5 introduces support for the `platform_python_implementation` -# environment marker: https://github.com/jaraco/setuptools/pull/28 -__requires__ = 'setuptools>=18.5' +__requires__ = 'setuptools>=54.0.0' -assert StrictVersion(setuptools.__version__) >= StrictVersion('18.5'), \ - 'Installation from source requires setuptools>=18.5.' +assert StrictVersion(setuptools.__version__) >= StrictVersion('54.0.0'), \ + 'Installation from source requires setuptools>=54.0.0' SETUP_DIR = os.path.dirname(__file__) @@ -178,7 +176,7 @@ CLASSIFIERS = [ setuptools.setup( name='django-ddp', - version='0.19.1', + version='0.20.0', description=__doc__, long_description=open('README.rst').read(), author='Tyson Clugg', @@ -197,46 +195,23 @@ setuptools.setup( __requires__, ], install_requires=[ - 'Django>=1.8', - 'meteor-ejson>=1.0', - 'psycogreen>=1.0', - 'pybars3>=0.9.1', - 'six>=1.10.0', + 'Django==1.11.29', + 'meteor-ejson==1.1.0', + 'psycogreen==1.0.2', + 'pybars3==0.9.7', + 'six==1.15.0', + 'gevent==21.1.2', + 'psycopg2==2.8.6', + 'gevent-websocket @ git+https://github.com/MEERQAT/gevent-websocket.git@v0.11.0#egg=gevent-websocket', ], extras_require={ - # We need gevent version dependent upon environment markers, but the - # extras_require seem to be a separate phase from setup/install of - # install_requires. So we specify gevent-websocket (which depends on - # gevent) here in order to honour environment markers. - '': [ - 'gevent-websocket>=0.9,!=0.9.4', - ], - # Django 1.9 doesn't support Python 3.3 - ':python_version=="3.3"': [ - 'Django<1.9', - ], - # CPython < 3.0 can use gevent 1.0 - ':platform_python_implementation=="CPython" and python_version<"3.0"': [ - 'gevent>=1.0', - ], - # everything else needs gevent 1.1 - ':platform_python_implementation!="CPython" or python_version>="3.0"': [ - 'gevent>=1.1rc2', - ], - # CPython can use plain old psycopg2 - ':platform_python_implementation=="CPython"': [ - 'psycopg2>=2.5.4', - ], - # everything else must use psycopg2cffi - ':platform_python_implementation != "CPython"': [ - 'psycopg2cffi>=2.7.2', - ], 'develop': [ # things you need to distribute a wheel from source (`make dist`) - 'Sphinx>=1.3.3', - 'Sphinx-PyPI-upload>=0.2.1', - 'twine>=1.6.4', - 'sphinxcontrib-dashbuilder>=0.1.0', + 'Sphinx==1.3.3', + 'Sphinx-PyPI-upload==0.2.1', + 'twine==1.6.4', + 'sphinxcontrib-dashbuilder==0.1.0', + 'rst2pdf==0.98', ], }, entry_points={ From 81a289b7882eeed471476a9036e458d78a54eef2 Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:42:56 +0200 Subject: [PATCH 2/7] [MQ-683] Ran `2to3` over package. --- dddp/__init__.py | 8 +++---- dddp/accounts/ddp.py | 16 ++++++------- dddp/accounts/tests.py | 2 +- dddp/admin.py | 4 ++-- dddp/alea.py | 2 +- dddp/api.py | 24 +++++++++---------- dddp/apps.py | 2 +- dddp/logging.py | 2 +- dddp/main.py | 6 ++--- dddp/migrations/0001_initial.py | 2 +- dddp/migrations/0002_auto_20150408_0321.py | 2 +- dddp/migrations/0003_auto_20150413_1328.py | 2 +- .../migrations/0004_connection_server_addr.py | 2 +- dddp/migrations/0005_auto_20150427_1209.py | 2 +- dddp/migrations/0006_auto_20150428_2245.py | 2 +- dddp/migrations/0007_auto_20150505_1302.py | 2 +- ...8_remove_subscription_publication_class.py | 2 +- dddp/migrations/0009_auto_20150812_0856.py | 2 +- dddp/models.py | 10 ++++---- dddp/tests.py | 6 ++--- dddp/views.py | 8 +++---- dddp/websocket.py | 4 ++-- 22 files changed, 55 insertions(+), 57 deletions(-) diff --git a/dddp/__init__.py b/dddp/__init__.py index 9458005..f7b302e 100644 --- a/dddp/__init__.py +++ b/dddp/__init__.py @@ -1,5 +1,5 @@ """Django/PostgreSQL implementation of the Meteor server.""" -from __future__ import unicode_literals + import sys from gevent.local import local from dddp import alea @@ -71,9 +71,9 @@ class MeteorError(Exception): error, reason, details, err_kwargs = self.args result = { key: val - for key, val in { + for key, val in list({ 'error': error, 'reason': reason, 'details': details, - }.items() + }.items()) if val is not None } result.update(err_kwargs) @@ -165,7 +165,7 @@ THREAD_LOCAL_FACTORIES = { 'user': lambda: None, } THREAD_LOCAL = this = ThreadLocal() # pylint: disable=invalid-name -METEOR_ID_CHARS = u'23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz' +METEOR_ID_CHARS = '23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz' def meteor_random_id(name=None, length=17): diff --git a/dddp/accounts/ddp.py b/dddp/accounts/ddp.py index b8c4abd..2863e4b 100644 --- a/dddp/accounts/ddp.py +++ b/dddp/accounts/ddp.py @@ -85,7 +85,7 @@ def iter_auth_hashes(user, purpose, minutes_valid): def get_auth_hash(user, purpose): """Generate a user hash for a particular purpose.""" - return iter_auth_hashes(user, purpose, minutes_valid=1).next() + return next(iter_auth_hashes(user, purpose, minutes_valid=1)) def calc_expiry_time(minutes_valid): @@ -185,7 +185,7 @@ class Users(Collection): """Return name prefixed by `key_prefix`.""" return '%s%s' % (key_prefix, name) - for key in profile.keys(): + for key in list(profile.keys()): val = getter(key) if key == prefixed('name'): result['full_name'] = val @@ -208,7 +208,7 @@ class Users(Collection): if len(update['$set']) != 0: raise MeteorError(400, 'Invalid update fields: %r') - for key, val in profile_update.items(): + for key, val in list(profile_update.items()): setattr(user, key, val) user.save() @@ -275,7 +275,7 @@ class Auth(APIMixin): ]) # first pass, send `added` for objs unique to `post` - for col_post, query in post.items(): + for col_post, query in list(post.items()): try: qs_pre = pre[col_post] query = query.exclude( @@ -288,7 +288,7 @@ class Auth(APIMixin): this.ws.send(col_post.obj_change_as_msg(obj, ADDED)) # second pass, send `removed` for objs unique to `pre` - for col_pre, query in pre.items(): + for col_pre, query in list(pre.items()): try: qs_post = post[col_pre] query = query.exclude( @@ -343,10 +343,10 @@ class Auth(APIMixin): def get_username(self, user): """Retrieve username from user selector.""" - if isinstance(user, basestring): + if isinstance(user, str): return user elif isinstance(user, dict) and len(user) == 1: - [(key, val)] = user.items() + [(key, val)] = list(user.items()) if key == 'username' or (key == self.user_model.USERNAME_FIELD): # username provided directly return val @@ -373,7 +373,7 @@ class Auth(APIMixin): @staticmethod def get_password(password): """Return password in plain-text from string/dict.""" - if isinstance(password, basestring): + if isinstance(password, str): # regular Django authentication - plaintext password... but you're # using HTTPS (SSL) anyway so it's protected anyway, right? return password diff --git a/dddp/accounts/tests.py b/dddp/accounts/tests.py index 04f53cc..8b836c1 100644 --- a/dddp/accounts/tests.py +++ b/dddp/accounts/tests.py @@ -1,5 +1,5 @@ """Django DDP Accounts test suite.""" -from __future__ import unicode_literals + import sys from dddp import tests diff --git a/dddp/admin.py b/dddp/admin.py index 9f5e780..2ffff68 100644 --- a/dddp/admin.py +++ b/dddp/admin.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from django.contrib import admin from django.core.urlresolvers import reverse, NoReverseMatch from django.utils.html import format_html @@ -7,7 +7,7 @@ from dddp import models def object_admin_link(obj): kwargs = { - 'format_string': u'{app_label}.{model} {object_id}: {object}', + 'format_string': '{app_label}.{model} {object_id}: {object}', 'app_label': obj.content_type.app_label, 'model': obj.content_type.model, 'object_id': obj.object_id, diff --git a/dddp/alea.py b/dddp/alea.py index 4b0bd42..2779386 100644 --- a/dddp/alea.py +++ b/dddp/alea.py @@ -49,7 +49,7 @@ True True """ -from __future__ import unicode_literals + from math import floor import os diff --git a/dddp/api.py b/dddp/api.py index e3eac98..eccf6c5 100644 --- a/dddp/api.py +++ b/dddp/api.py @@ -1,5 +1,5 @@ """Django DDP API, Collections, Cursors and Publications.""" -from __future__ import absolute_import, unicode_literals, print_function + # standard library import collections @@ -241,7 +241,7 @@ class Collection(APIMixin): if user_rels: if user is None: return qs.none() # no user but we need one: return no objects. - if isinstance(user_rels, basestring): + if isinstance(user_rels, str): user_rels = [user_rels] user_filter = None # Django supports model._meta -> pylint: disable=W0212 @@ -283,7 +283,7 @@ class Collection(APIMixin): if obj.pk is None: return user_ids # nobody can see objects that don't exist user_rels = self.user_rel - if isinstance(user_rels, basestring): + if isinstance(user_rels, str): user_rels = [user_rels] user_rel_map = { '_user_rel_%d' % index: ArrayAgg(user_rel) @@ -303,7 +303,7 @@ class Collection(APIMixin): ).annotate( **user_rel_map ).values_list( - *user_rel_map.keys() + *list(user_rel_map.keys()) ).get(): user_ids.update(rel_user_ids) user_ids.difference_update([None]) @@ -411,15 +411,15 @@ class Collection(APIMixin): """Generate a DDP msg for obj with specified msg type.""" # check for F expressions exps = [ - name for name, val in vars(obj).items() + name for name, val in list(vars(obj).items()) if isinstance(val, ExpressionNode) ] if exps: # clone/update obj with values but only for the expression fields obj = deepcopy(obj) - for name, val in self.model.objects.values(*exps).get( + for name, val in list(self.model.objects.values(*exps).get( pk=obj.pk, - ).items(): + ).items()): setattr(obj, name, val) # run serialization now all fields are "concrete" (not F expressions) @@ -448,9 +448,9 @@ class Collection(APIMixin): # This will be sent as the `id`, don't send it in `fields`. fields.pop(field.name) for field in meta.local_many_to_many: - fields['%s_ids' % field.name] = get_meteor_ids( + fields['%s_ids' % field.name] = list(get_meteor_ids( field.rel.to, fields.pop(field.name), - ).values() + ).values()) return data def obj_change_as_msg(self, obj, msg, meteor_ids=None): @@ -572,7 +572,7 @@ class DDP(APIMixin): @property def api_providers(self): """Return an iterable of API providers.""" - return self._registry.values() + return list(self._registry.values()) def qs_and_collection(self, qs): """Return (qs, collection) from qs (which may be a tuple).""" @@ -608,7 +608,7 @@ class DDP(APIMixin): ), ) for col, qs - in queries.items() + in list(queries.items()) ) for other in Subscription.objects.filter( connection=obj.connection_id, @@ -628,7 +628,7 @@ class DDP(APIMixin): *args, **kwargs ).values('pk'), ) - for col, qs in to_send.items(): + for col, qs in list(to_send.items()): yield col, qs.distinct() @api_endpoint diff --git a/dddp/apps.py b/dddp/apps.py index e233d23..13cafdd 100644 --- a/dddp/apps.py +++ b/dddp/apps.py @@ -19,7 +19,7 @@ class DjangoDDPConfig(AppConfig): """Initialisation for django-ddp (setup lookups and signal handlers).""" if not settings.DATABASES: raise ImproperlyConfigured('No databases configured.') - for (alias, conf) in settings.DATABASES.items(): + for (alias, conf) in list(settings.DATABASES.items()): engine = conf['ENGINE'] if engine not in [ 'django.db.backends.postgresql', diff --git a/dddp/logging.py b/dddp/logging.py index dcf6945..ecee858 100644 --- a/dddp/logging.py +++ b/dddp/logging.py @@ -1,5 +1,5 @@ """Django DDP logging helpers.""" -from __future__ import absolute_import, print_function + import datetime import logging diff --git a/dddp/main.py b/dddp/main.py index dd8d12c..0eb0171 100644 --- a/dddp/main.py +++ b/dddp/main.py @@ -1,7 +1,5 @@ """Django DDP WebSocket service.""" -from __future__ import absolute_import, print_function - import argparse import collections import os @@ -157,7 +155,7 @@ class DDPLauncher(object): listen_addr, self.resource, debug=debug, - **{key: val for key, val in ssl_args.items() if val is not None} + **{key: val for key, val in list(ssl_args.items()) if val is not None} ) def get_backdoor_server(self, listen_addr, **context): @@ -286,7 +284,7 @@ def serve(listen, verbosity=1, debug_port=0, **ssl_args): sigmap = { val: name for name, val - in vars(signal).items() + in list(vars(signal).items()) if name.startswith('SIG') } diff --git a/dddp/migrations/0001_initial.py b/dddp/migrations/0001_initial.py index c493424..2c4495c 100644 --- a/dddp/migrations/0001_initial.py +++ b/dddp/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations import dddp.models diff --git a/dddp/migrations/0002_auto_20150408_0321.py b/dddp/migrations/0002_auto_20150408_0321.py index 62c4959..32f9924 100644 --- a/dddp/migrations/0002_auto_20150408_0321.py +++ b/dddp/migrations/0002_auto_20150408_0321.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations from django.conf import settings diff --git a/dddp/migrations/0003_auto_20150413_1328.py b/dddp/migrations/0003_auto_20150413_1328.py index 470ffa6..a0c2602 100644 --- a/dddp/migrations/0003_auto_20150413_1328.py +++ b/dddp/migrations/0003_auto_20150413_1328.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations diff --git a/dddp/migrations/0004_connection_server_addr.py b/dddp/migrations/0004_connection_server_addr.py index a045855..278c42f 100644 --- a/dddp/migrations/0004_connection_server_addr.py +++ b/dddp/migrations/0004_connection_server_addr.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations diff --git a/dddp/migrations/0005_auto_20150427_1209.py b/dddp/migrations/0005_auto_20150427_1209.py index c7adc86..f53056b 100644 --- a/dddp/migrations/0005_auto_20150427_1209.py +++ b/dddp/migrations/0005_auto_20150427_1209.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations from django.conf import settings diff --git a/dddp/migrations/0006_auto_20150428_2245.py b/dddp/migrations/0006_auto_20150428_2245.py index d579c7a..f7dde7c 100644 --- a/dddp/migrations/0006_auto_20150428_2245.py +++ b/dddp/migrations/0006_auto_20150428_2245.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations diff --git a/dddp/migrations/0007_auto_20150505_1302.py b/dddp/migrations/0007_auto_20150505_1302.py index 4fbec54..faefe5b 100644 --- a/dddp/migrations/0007_auto_20150505_1302.py +++ b/dddp/migrations/0007_auto_20150505_1302.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations diff --git a/dddp/migrations/0008_remove_subscription_publication_class.py b/dddp/migrations/0008_remove_subscription_publication_class.py index 8f2b441..310152f 100644 --- a/dddp/migrations/0008_remove_subscription_publication_class.py +++ b/dddp/migrations/0008_remove_subscription_publication_class.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations diff --git a/dddp/migrations/0009_auto_20150812_0856.py b/dddp/migrations/0009_auto_20150812_0856.py index 3247443..9e922eb 100644 --- a/dddp/migrations/0009_auto_20150812_0856.py +++ b/dddp/migrations/0009_auto_20150812_0856.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import models, migrations import dddp.models diff --git a/dddp/models.py b/dddp/models.py index 28c52e1..d952d97 100644 --- a/dddp/models.py +++ b/dddp/models.py @@ -1,5 +1,5 @@ """Django DDP models.""" -from __future__ import absolute_import + import collections import os @@ -109,7 +109,7 @@ def get_meteor_ids(model, object_ids): ).values_list('object_id', 'meteor_id') for obj_pk, meteor_id in query: result[str(obj_pk)] = meteor_id - for obj_pk, meteor_id in result.items(): + for obj_pk, meteor_id in list(result.items()): if meteor_id is None: result[obj_pk] = get_meteor_id(model, obj_pk) return result @@ -309,7 +309,7 @@ class Connection(models.Model, object): def __str__(self): """Text representation of subscription.""" - return u'%s/\u200b%s' % ( + return '%s/\u200b%s' % ( self.connection_id, self.remote_addr, ) @@ -337,7 +337,7 @@ class Subscription(models.Model, object): def __str__(self): """Text representation of subscription.""" - return u'%s/\u200b%s/\u200b%s: %s%s' % ( + return '%s/\u200b%s/\u200b%s: %s%s' % ( self.user, self.connection_id, self.sub_id, @@ -367,7 +367,7 @@ class SubscriptionCollection(models.Model): def __str__(self): """Human readable representation of colleciton for a subscription.""" - return u'%s \u200b %s (%s)' % ( + return '%s \u200b %s (%s)' % ( self.subscription, self.collection_name, self.model_name, diff --git a/dddp/tests.py b/dddp/tests.py index 3286ae1..7c3581e 100644 --- a/dddp/tests.py +++ b/dddp/tests.py @@ -1,5 +1,5 @@ """Django DDP test suite.""" -from __future__ import absolute_import, unicode_literals + import doctest import errno @@ -136,7 +136,7 @@ class DDPTestServer(object): """DDP server with auto start and stop.""" server_addr = '127.0.0.1' - server_port_range = range(8000, 8080) + server_port_range = list(range(8000, 8080)) ssl_certfile_path = None ssl_keyfile_path = None @@ -404,7 +404,7 @@ def load_tests(loader, tests, pattern): del pattern suite = unittest.TestSuite() # add all TestCase classes from this (current) module - for attr in globals().values(): + for attr in list(globals().values()): if attr is DDPServerTestCase: continue # not meant to be executed, is has no tests. try: diff --git a/dddp/views.py b/dddp/views.py index 648a7ca..2124808 100644 --- a/dddp/views.py +++ b/dddp/views.py @@ -1,5 +1,5 @@ """Django DDP Server views.""" -from __future__ import absolute_import, unicode_literals + from copy import deepcopy import io @@ -26,7 +26,7 @@ def dict_merge(lft, rgt): if not isinstance(rgt, dict): return rgt result = deepcopy(lft) - for key, val in rgt.iteritems(): + for key, val in rgt.items(): if key in result and isinstance(result[key], dict): result[key] = dict_merge(result[key], val) else: @@ -233,11 +233,11 @@ class MeteorView(View): 'inline': None, 'head': read( self.internal_map.get('head', {}).get('path_full', None), - default=u'', + default='', ), 'body': read( self.internal_map.get('body', {}).get('path_full', None), - default=u'', + default='', ), } tmpl_raw = read(self.template_path, encoding='utf8') diff --git a/dddp/websocket.py b/dddp/websocket.py index 940512f..ea4a909 100644 --- a/dddp/websocket.py +++ b/dddp/websocket.py @@ -1,6 +1,6 @@ """Django DDP WebSocket service.""" -from __future__ import absolute_import, print_function + import atexit import collections @@ -332,7 +332,7 @@ class DDPWebSocketApplication(geventwebsocket.WebSocketApplication): safe_call(self.logger.debug, 'TX found %d', self._tx_next_id) # advance next message ID self._tx_next_id = next(self._tx_next_id_gen) - if not isinstance(data, basestring): + if not isinstance(data, str): # ejson payload msg = data.get('msg', None) if msg in (ADDED, CHANGED, REMOVED): From 114c04b3b80f063c3aecdd26adc1cf32fe3740fd Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:43:25 +0200 Subject: [PATCH 3/7] [MQ-683] Fixed compatibility issues not covered by `2to3`. --- dddp/accounts/ddp.py | 36 ++++++++++++++++++++---------------- dddp/postgres.py | 4 ++-- dddp/websocket.py | 4 ++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/dddp/accounts/ddp.py b/dddp/accounts/ddp.py index 2863e4b..0851b7e 100644 --- a/dddp/accounts/ddp.py +++ b/dddp/accounts/ddp.py @@ -9,6 +9,7 @@ from binascii import Error import collections import datetime import hashlib +import base64 from ejson import loads, dumps @@ -72,15 +73,14 @@ def iter_auth_hashes(user, purpose, minutes_valid): """ now = timezone.now().replace(microsecond=0, second=0) for minute in range(minutes_valid + 1): - yield hashlib.sha1( - '%s:%s:%s:%s:%s' % ( - now - datetime.timedelta(minutes=minute), - user.password, - purpose, - user.pk, - settings.SECRET_KEY, - ), - ).hexdigest() + _content = '%s:%s:%s:%s:%s' % ( + now - datetime.timedelta(minutes=minute), + user.password, + purpose, + user.pk, + settings.SECRET_KEY, + ) + yield hashlib.sha1(_content.encode()).hexdigest() def get_auth_hash(user, purpose): @@ -97,15 +97,19 @@ def calc_expiry_time(minutes_valid): def get_user_token(user, purpose, minutes_valid): """Return login token info for given user.""" - token = ''.join( - dumps([ - user.get_username(), - get_auth_hash(user, purpose), - ]).encode('base64').split('\n') + token_json = dumps([ + user.get_username(), + get_auth_hash(user, purpose), + ]) + token_json_enc = token_json.encode() + token_json_enc_b64_multiline = base64.b64encode(token_json_enc) + token_json_enc_b64_singleline = "".join( + token_json_enc_b64_multiline.decode().split("\n") ) + return { 'id': get_meteor_id(user), - 'token': token, + 'token': token_json_enc_b64_singleline, 'tokenExpires': calc_expiry_time(minutes_valid), } @@ -314,7 +318,7 @@ class Auth(APIMixin): def validated_user(cls, token, purpose, minutes_valid): """Resolve and validate auth token, returns user object.""" try: - username, auth_hash = loads(token.decode('base64')) + username, auth_hash = loads(base64.b64decode(token)) except (ValueError, Error): cls.auth_failed(token=token) try: diff --git a/dddp/postgres.py b/dddp/postgres.py index 419b103..71c0d33 100644 --- a/dddp/postgres.py +++ b/dddp/postgres.py @@ -1,6 +1,6 @@ """Django DDP PostgreSQL Greenlet.""" -from __future__ import absolute_import + import ejson import gevent @@ -39,7 +39,7 @@ class PostgresGreenlet(gevent.Greenlet): # http://www.postgresql.org/docs/current/static/libpq-connect.html # section 31.1.2 (Parameter Key Words) for details on available params. conn_params.update( - async=True, + async_=True, application_name='{} pid={} django-ddp'.format( socket.gethostname(), # hostname os.getpid(), # PID diff --git a/dddp/websocket.py b/dddp/websocket.py index ea4a909..0f63edd 100644 --- a/dddp/websocket.py +++ b/dddp/websocket.py @@ -153,8 +153,8 @@ class DDPWebSocketApplication(geventwebsocket.WebSocketApplication): # `_tx_buffer` collects outgoing messages which must be sent in order self._tx_buffer = {} # track the head of the queue (buffer) and the next msg to be sent - self._tx_buffer_id_gen = itertools.cycle(irange(sys.maxint)) - self._tx_next_id_gen = itertools.cycle(irange(sys.maxint)) + self._tx_buffer_id_gen = itertools.cycle(irange(sys.maxsize)) + self._tx_next_id_gen = itertools.cycle(irange(sys.maxsize)) # start by waiting for the very first message self._tx_next_id = next(self._tx_next_id_gen) From ca1ee1ed57f1f34d10103b8d8eea00924cfe3c80 Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:43:31 +0200 Subject: [PATCH 4/7] [MQ-683] Updated ignores. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c41cec0..fec2105 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ docs/node_modules/ # meteor test/build/ test/meteor_todos/.meteor/ +/.idea From 5165b93363f0b3273498c724785801d30a37ab1d Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:56:10 +0200 Subject: [PATCH 5/7] [MQ-683] Fixed import error. --- dddp/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dddp/main.py b/dddp/main.py index 0eb0171..6b9035f 100644 --- a/dddp/main.py +++ b/dddp/main.py @@ -9,6 +9,7 @@ import gevent from gevent.backdoor import BackdoorServer import gevent.event import gevent.pywsgi +import gevent.signal import geventwebsocket import geventwebsocket.handler @@ -297,7 +298,7 @@ def serve(listen, verbosity=1, debug_port=0, **ssl_args): ) launcher.stop() for signum in [signal.SIGINT, signal.SIGQUIT]: - gevent.signal(signum, sighandler) + gevent.signal.signal(signum, sighandler) launcher.run() From 589704283b9c16e0006ccfdcd82ff601b22e4822 Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Thu, 4 Mar 2021 08:56:32 +0200 Subject: [PATCH 6/7] Bumped version. --- dddp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dddp/__init__.py b/dddp/__init__.py index f7b302e..4a9d7ae 100644 --- a/dddp/__init__.py +++ b/dddp/__init__.py @@ -4,7 +4,7 @@ import sys from gevent.local import local from dddp import alea -__version__ = '0.19.1' +__version__ = '0.20.0' __url__ = 'https://github.com/django-ddp/django-ddp' default_app_config = 'dddp.apps.DjangoDDPConfig' From 6e6f56742f91063978fb9ad46aac185325582c33 Mon Sep 17 00:00:00 2001 From: Adamos Kyriakou Date: Tue, 9 Mar 2021 11:18:00 +0200 Subject: [PATCH 7/7] [MQ-683] Fixed bug caused by reading files in ASCII mode. --- dddp/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dddp/views.py b/dddp/views.py index 2124808..44138b7 100644 --- a/dddp/views.py +++ b/dddp/views.py @@ -271,7 +271,7 @@ class MeteorView(View): ) try: file_path, content_type = self.url_map[path] - with open(file_path, 'r') as content: + with open(file_path, 'rb') as content: return HttpResponse( content.read(), content_type=content_type,