From a53a3806877f9487cd326f0014b9db697f066bcd Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Tue, 17 Sep 2019 08:10:03 -0600 Subject: [PATCH 01/15] Updated to minimal working state with python 3 --- exchange/cache.py | 10 +++++++--- exchange/utils.py | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/exchange/cache.py b/exchange/cache.py index e90540a..ab0c4f3 100644 --- a/exchange/cache.py +++ b/exchange/cache.py @@ -1,4 +1,4 @@ -from django.core.cache import get_cache +from django.core.cache import cache from django.conf import settings from exchange.models import ExchangeRate @@ -20,8 +20,12 @@ CACHE_TIMEOUT = 0 # Not configurable at all -cache = get_cache(CACHE_DATABASE) - +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', + 'LOCATION': CACHE_DATABASE, + } +} def _get_cache_key(source_currency, target_currency): return ':'.join([CACHE_KEY_PREFIX, source_currency, target_currency]) diff --git a/exchange/utils.py b/exchange/utils.py index 41c254e..80ad4a2 100644 --- a/exchange/utils.py +++ b/exchange/utils.py @@ -21,7 +21,7 @@ def import_class(class_path): module_name = '.'.join(class_path.split(".")[:-1]) mod = import_module(module_name) return getattr(mod, class_path.split(".")[-1]) - except Exception, detail: + except Exception as detail: raise ImportError(detail) @@ -86,7 +86,7 @@ def update_many(objects, fields=[], using="default"): parameters = [] for o in objects: parameters.append(tuple(f.get_db_prep_save(f.pre_save(o, True), - connection=con) for f in fields_with_pk)) + connection=con) for f in fields_with_pk)) table = meta.db_table assignments = ",".join(("%s=%%s" % con.ops.quote_name(f.column)) From 7c727a801373ae80e1314145cb6d45ddfafc7b93 Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Tue, 17 Sep 2019 10:59:28 -0600 Subject: [PATCH 02/15] Deleted migrations to update from south --- exchange/migrations/0001_initial.py | 53 ------------------- .../0002_auto__chg_field_exchangerate_rate.py | 36 ------------- 2 files changed, 89 deletions(-) delete mode 100644 exchange/migrations/0001_initial.py delete mode 100644 exchange/migrations/0002_auto__chg_field_exchangerate_rate.py diff --git a/exchange/migrations/0001_initial.py b/exchange/migrations/0001_initial.py deleted file mode 100644 index 52d041b..0000000 --- a/exchange/migrations/0001_initial.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding model 'Currency' - db.create_table(u'exchange_currency', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('code', self.gf('django.db.models.fields.CharField')(unique=True, max_length=3)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=64)), - )) - db.send_create_signal(u'exchange', ['Currency']) - - # Adding model 'ExchangeRate' - db.create_table(u'exchange_exchangerate', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='rates', to=orm['exchange.Currency'])), - ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exchange.Currency'])), - ('rate', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2)), - )) - db.send_create_signal(u'exchange', ['ExchangeRate']) - - - def backwards(self, orm): - # Deleting model 'Currency' - db.delete_table(u'exchange_currency') - - # Deleting model 'ExchangeRate' - db.delete_table(u'exchange_exchangerate') - - - models = { - u'exchange.currency': { - 'Meta': {'object_name': 'Currency'}, - 'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}) - }, - u'exchange.exchangerate': { - 'Meta': {'object_name': 'ExchangeRate'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'rate': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rates'", 'to': u"orm['exchange.Currency']"}), - 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['exchange.Currency']"}) - } - } - - complete_apps = ['exchange'] \ No newline at end of file diff --git a/exchange/migrations/0002_auto__chg_field_exchangerate_rate.py b/exchange/migrations/0002_auto__chg_field_exchangerate_rate.py deleted file mode 100644 index d22b52e..0000000 --- a/exchange/migrations/0002_auto__chg_field_exchangerate_rate.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Changing field 'ExchangeRate.rate' - db.alter_column(u'exchange_exchangerate', 'rate', self.gf('django.db.models.fields.DecimalField')(max_digits=17, decimal_places=8)) - - def backwards(self, orm): - - # Changing field 'ExchangeRate.rate' - db.alter_column(u'exchange_exchangerate', 'rate', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2)) - - models = { - u'exchange.currency': { - 'Meta': {'object_name': 'Currency'}, - 'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}) - }, - u'exchange.exchangerate': { - 'Meta': {'object_name': 'ExchangeRate'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'rate': ('django.db.models.fields.DecimalField', [], {'max_digits': '17', 'decimal_places': '8'}), - 'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rates'", 'to': u"orm['exchange.Currency']"}), - 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['exchange.Currency']"}) - } - } - - complete_apps = ['exchange'] \ No newline at end of file From 7fd5ef3aebbf8ae166301a753917a02c69ba79d3 Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Tue, 17 Sep 2019 11:06:56 -0600 Subject: [PATCH 03/15] Adds migration file using django instead of south --- exchange/admin.py | 2 +- exchange/migrations/0001_initial.py | 41 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 exchange/migrations/0001_initial.py diff --git a/exchange/admin.py b/exchange/admin.py index 476b876..56a707e 100644 --- a/exchange/admin.py +++ b/exchange/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from models import Currency, ExchangeRate +from .models import Currency, ExchangeRate admin.site.register(Currency) admin.site.register(ExchangeRate) diff --git a/exchange/migrations/0001_initial.py b/exchange/migrations/0001_initial.py new file mode 100644 index 0000000..3dcb73f --- /dev/null +++ b/exchange/migrations/0001_initial.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-09-17 17:05 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Currency', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False)), + ('code', models.CharField(max_length=3, unique=True)), + ('name', models.CharField(max_length=64)), + ], + options={ + 'verbose_name_plural': 'currencies', + }, + ), + migrations.CreateModel( + name='ExchangeRate', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False)), + ('rate', models.DecimalField(decimal_places=8, max_digits=17)), + ('source', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='rates', to='exchange.Currency')), + ('target', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='exchange.Currency')), + ], + ), + ] From 4d554ee103ed4e92ffa1962a9f70e54d95949e3c Mon Sep 17 00:00:00 2001 From: Barrett Date: Wed, 6 Nov 2019 09:33:21 -0700 Subject: [PATCH 04/15] update importlib import, fix syntax error in except --- exchange/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exchange/utils.py b/exchange/utils.py index 41c254e..9b5e810 100644 --- a/exchange/utils.py +++ b/exchange/utils.py @@ -17,11 +17,11 @@ def import_class(class_path): 'OrderedDict' """ try: - from django.utils.importlib import import_module + from importlib import import_module module_name = '.'.join(class_path.split(".")[:-1]) mod = import_module(module_name) return getattr(mod, class_path.split(".")[-1]) - except Exception, detail: + except Exception as detail: raise ImportError(detail) From cc7be6abe67ad874cf00480370830feee6ec91b5 Mon Sep 17 00:00:00 2001 From: Barrett Date: Wed, 6 Nov 2019 11:29:42 -0700 Subject: [PATCH 05/15] change importlib import --- exchange/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/utils.py b/exchange/utils.py index 80ad4a2..1f7860b 100644 --- a/exchange/utils.py +++ b/exchange/utils.py @@ -17,7 +17,7 @@ def import_class(class_path): 'OrderedDict' """ try: - from django.utils.importlib import import_module + from importlib import import_module module_name = '.'.join(class_path.split(".")[:-1]) mod = import_module(module_name) return getattr(mod, class_path.split(".")[-1]) From 9f1f9ba286894aef90baec729a75beb455e3577a Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Thu, 7 Nov 2019 08:19:12 -0700 Subject: [PATCH 06/15] Updates currency to 19 decimal places to avoid error --- exchange/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/models.py b/exchange/models.py index 9640af3..d669571 100644 --- a/exchange/models.py +++ b/exchange/models.py @@ -22,7 +22,7 @@ class ExchangeRate(models.Model): """Model to persist exchange rates between currencies""" source = models.ForeignKey('exchange.Currency', related_name='rates') target = models.ForeignKey('exchange.Currency') - rate = models.DecimalField(max_digits=17, decimal_places=8) + rate = models.DecimalField(max_digits=19, decimal_places=8) objects = ExchangeRateManager() From ec41e36fccb95fcee4985c14adf6d3249f35583d Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Thu, 7 Nov 2019 08:33:12 -0700 Subject: [PATCH 07/15] Adds migration to increase max_length of currency amount --- .../migrations/0002_auto_20191107_1532.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 exchange/migrations/0002_auto_20191107_1532.py diff --git a/exchange/migrations/0002_auto_20191107_1532.py b/exchange/migrations/0002_auto_20191107_1532.py new file mode 100644 index 0000000..9745930 --- /dev/null +++ b/exchange/migrations/0002_auto_20191107_1532.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-11-07 15:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('exchange', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='rate', + field=models.DecimalField(decimal_places=8, max_digits=19), + ), + ] From b1a14a3da0fd8b74d348ca4ab5b81cf047c6fc45 Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Thu, 7 Nov 2019 13:39:55 -0700 Subject: [PATCH 08/15] removed depricated code, transactions autocommitted in newer django --- exchange/utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/exchange/utils.py b/exchange/utils.py index 1f7860b..1918ef3 100644 --- a/exchange/utils.py +++ b/exchange/utils.py @@ -54,7 +54,6 @@ def insert_many(objects, using="default"): placeholders = ",".join(("%s",) * len(fields)) con.cursor().executemany("insert into %s (%s) values (%s)" % (table, column_names, placeholders), parameters) - transaction.commit_unless_managed(using=using) def update_many(objects, fields=[], using="default"): @@ -95,7 +94,6 @@ def update_many(objects, fields=[], using="default"): % (table, assignments, con.ops.quote_name(meta.pk.column)), parameters) - transaction.commit_unless_managed(using=using) def memoize(ttl=None): From 298e8385ef923a020b6b3d4935ca551e9803c485 Mon Sep 17 00:00:00 2001 From: Barrett Date: Mon, 6 Jan 2020 13:44:06 -0700 Subject: [PATCH 09/15] add on_delete to model foreign keys for django 2 update --- exchange/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exchange/models.py b/exchange/models.py index d669571..643bc29 100644 --- a/exchange/models.py +++ b/exchange/models.py @@ -20,8 +20,8 @@ def get_numeric_code(self): class ExchangeRate(models.Model): """Model to persist exchange rates between currencies""" - source = models.ForeignKey('exchange.Currency', related_name='rates') - target = models.ForeignKey('exchange.Currency') + source = models.ForeignKey('exchange.Currency', related_name='rates', null=True, on_delete=models.CASCADE) + target = models.ForeignKey('exchange.Currency', null=True, on_delete=models.CASCADE)) rate = models.DecimalField(max_digits=19, decimal_places=8) objects = ExchangeRateManager() From b155bb944aa424c43a551af4164fbec14e9f2d84 Mon Sep 17 00:00:00 2001 From: Barrett Date: Mon, 6 Jan 2020 13:45:56 -0700 Subject: [PATCH 10/15] remove typo --- exchange/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/models.py b/exchange/models.py index 643bc29..5d06781 100644 --- a/exchange/models.py +++ b/exchange/models.py @@ -21,7 +21,7 @@ def get_numeric_code(self): class ExchangeRate(models.Model): """Model to persist exchange rates between currencies""" source = models.ForeignKey('exchange.Currency', related_name='rates', null=True, on_delete=models.CASCADE) - target = models.ForeignKey('exchange.Currency', null=True, on_delete=models.CASCADE)) + target = models.ForeignKey('exchange.Currency', null=True, on_delete=models.CASCADE) rate = models.DecimalField(max_digits=19, decimal_places=8) objects = ExchangeRateManager() From 7b41f67ec92f886857e6e462058755125f383049 Mon Sep 17 00:00:00 2001 From: Justin Clark Date: Wed, 22 Jan 2020 15:01:23 -0700 Subject: [PATCH 11/15] adding new migration --- .../migrations/0003_auto_20200122_2156.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 exchange/migrations/0003_auto_20200122_2156.py diff --git a/exchange/migrations/0003_auto_20200122_2156.py b/exchange/migrations/0003_auto_20200122_2156.py new file mode 100644 index 0000000..4147414 --- /dev/null +++ b/exchange/migrations/0003_auto_20200122_2156.py @@ -0,0 +1,26 @@ +# Generated by Django 2.2 on 2020-01-22 21:56 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('exchange', '0002_auto_20191107_1532'), + ] + + operations = [ + migrations.AlterField( + model_name='exchangerate', + name='source', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, + related_name='rates', to='exchange.Currency'), + ), + migrations.AlterField( + model_name='exchangerate', + name='target', + field=models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to='exchange.Currency'), + ), + ] From d07127aa3783d736735142934315bb68ab6e2d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Hern=C3=A1ndez?= Date: Fri, 21 Jan 2022 18:55:56 +0100 Subject: [PATCH 12/15] Handle KeyError exception when a Currecy code does not exists in the api response --- exchange/adapters/__init__.py | 43 ++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/exchange/adapters/__init__.py b/exchange/adapters/__init__.py index 80aea0c..23753f6 100644 --- a/exchange/adapters/__init__.py +++ b/exchange/adapters/__init__.py @@ -38,24 +38,31 @@ def update(self): currencies = list(Currency.objects.all()) for source in currencies: for target in currencies: - rate = self._get_rate_through_usd(source.code, - target.code, - usd_exchange_rates) - - exchange_rate = ExchangeRate(source=source, - target=target, - rate=rate) - - if (source.code, target.code) in existing: - exchange_rate.id = existing[(source.code, target.code)] - updates.append(exchange_rate) - logger.debug('exchange rate updated %s/%s=%s' - % (source, target, rate)) - else: - inserts.append(exchange_rate) - logger.debug('exchange rate created %s/%s=%s' - % (source, target, rate)) - + try: + rate = self._get_rate_through_usd(source.code, + target.code, + usd_exchange_rates) + + exchange_rate = ExchangeRate(source=source, + target=target, + rate=rate) + + if (source.code, target.code) in existing: + exchange_rate.id = existing[(source.code, target.code)] + updates.append(exchange_rate) + logger.debug('exchange rate updated %s/%s=%s' + % (source, target, rate)) + else: + inserts.append(exchange_rate) + logger.debug('exchange rate created %s/%s=%s' + % (source, target, rate)) + except KeyError as e: + logger.exception('Failed to update exchange rate %s/%s. %s' % (source, target, str(e.message))) + continue + except Exception as e: + logger.exception(e) + continue + logger.info('exchange rates updated for %s' % source.code) logger.info("Updating %s rows" % len(updates)) update_many(updates) From 7b701706326ecab45923e26b2cf6ede0fc59380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Hern=C3=A1ndez?= Date: Tue, 25 Jan 2022 20:49:56 +0100 Subject: [PATCH 13/15] Fixed exception message --- exchange/adapters/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/adapters/__init__.py b/exchange/adapters/__init__.py index 23753f6..28a2f27 100644 --- a/exchange/adapters/__init__.py +++ b/exchange/adapters/__init__.py @@ -57,7 +57,7 @@ def update(self): logger.debug('exchange rate created %s/%s=%s' % (source, target, rate)) except KeyError as e: - logger.exception('Failed to update exchange rate %s/%s. %s' % (source, target, str(e.message))) + logger.exception('Failed to update exchange rate %s/%s.' % (source.code, target.code)) continue except Exception as e: logger.exception(e) From f568a1bcadc7aa4a036804b726a4a6134b8c22b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Hern=C3=A1ndez?= Date: Tue, 22 Feb 2022 15:58:46 -0300 Subject: [PATCH 14/15] Added Currency.active field --- exchange/adapters/__init__.py | 2 +- exchange/models.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/exchange/adapters/__init__.py b/exchange/adapters/__init__.py index 28a2f27..a35415f 100644 --- a/exchange/adapters/__init__.py +++ b/exchange/adapters/__init__.py @@ -35,7 +35,7 @@ def update(self): updates = [] inserts = [] - currencies = list(Currency.objects.all()) + currencies = list(Currency.objects.filter(active=True)) for source in currencies: for target in currencies: try: diff --git a/exchange/models.py b/exchange/models.py index 5d06781..abdd950 100644 --- a/exchange/models.py +++ b/exchange/models.py @@ -7,6 +7,7 @@ class Currency(models.Model): """Model holds a currency information for a nationality""" code = models.CharField(max_length=3, unique=True) name = models.CharField(max_length=64) + active = models.BooleanField(default=True, help_text='Denotes whether or not the currency its being used and should update the exchange rates.') class Meta: verbose_name_plural = 'currencies' From b65e5c75e259f3bfd5b78f2e644dc8e6b248593e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Hern=C3=A1ndez?= Date: Thu, 24 Feb 2022 19:33:08 -0300 Subject: [PATCH 15/15] Added missing migrations --- exchange/migrations/0004_currency_active.py | 18 ++++++++++++++ .../migrations/0005_auto_20220224_2220.py | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 exchange/migrations/0004_currency_active.py create mode 100644 exchange/migrations/0005_auto_20220224_2220.py diff --git a/exchange/migrations/0004_currency_active.py b/exchange/migrations/0004_currency_active.py new file mode 100644 index 0000000..6c34be9 --- /dev/null +++ b/exchange/migrations/0004_currency_active.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2022-02-23 22:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('exchange', '0003_auto_20200122_2156'), + ] + + operations = [ + migrations.AddField( + model_name='currency', + name='active', + field=models.BooleanField(default=True), + ), + ] diff --git a/exchange/migrations/0005_auto_20220224_2220.py b/exchange/migrations/0005_auto_20220224_2220.py new file mode 100644 index 0000000..fb75c80 --- /dev/null +++ b/exchange/migrations/0005_auto_20220224_2220.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.24 on 2022-02-24 22:20 + +from django.db import migrations + +def commit_old_currencies_deactivation(apps, schema_editor): + Currency = apps.get_model("exchange", "Currency") + db_alias = schema_editor.connection.alias + Currency.objects.using(db_alias).filter(code__in=["MRO", "VEF"]).update(active=False) + + +def rollback_old_currencies_deactivation(apps, schema_editor): + Currency = apps.get_model("exchange", "Currency") + db_alias = schema_editor.connection.alias + Currency.objects.using(db_alias).filter(code__in=["MRO", "VEF"]).update(active=True) + +class Migration(migrations.Migration): + + dependencies = [ + ('exchange', '0004_currency_active'), + ] + + operations = [ + migrations.RunPython(commit_old_currencies_deactivation, rollback_old_currencies_deactivation), + ]