From f6da0d075f51c8b09140576fab82379ecafeb153 Mon Sep 17 00:00:00 2001 From: Brian Kohan Date: Mon, 20 Nov 2023 20:42:05 -0800 Subject: [PATCH] fixes #131 --- doc/requirements.txt | 2 +- doc/source/changelog.rst | 5 +++ pyproject.toml | 2 +- render_static/__init__.py | 2 +- render_static/tests/js_tests.py | 29 ++++++++++++ render_static/transpilers/enums_to_js.py | 57 +++++++++++++----------- 6 files changed, 68 insertions(+), 29 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index e498a1a..a6bb32e 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -7,4 +7,4 @@ sphinxcontrib-jsmath==1.0.1; python_version >= "3.5" sphinxcontrib-qthelp==1.0.3; python_version >= "3.5" sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.5" sphinx-js==3.2.2; python_version >= "3.5" -django-render-static==2.1.0 +django-render-static==2.1.1 diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 201526e..f9d0914 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -2,6 +2,11 @@ Change Log ========== +v2.1.1 +====== + +* Fixed `include_properties can result in non-deterministic ordering of constructor parameters that changes render to render `_ + v2.1.0 ====== * Implemented `Support templating of destination paths. `_ diff --git a/pyproject.toml b/pyproject.toml index a536efe..4471c93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-render-static" -version = "2.1.0" +version = "2.1.1" description = "Use Django's template engine to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript." authors = ["Brian Kohan "] license = "MIT" diff --git a/render_static/__init__.py b/render_static/__init__.py index 0392bd9..5e29173 100755 --- a/render_static/__init__.py +++ b/render_static/__init__.py @@ -14,7 +14,7 @@ from .transpilers.enums_to_js import EnumClassWriter from .transpilers.urls_to_js import ClassURLWriter, SimpleURLWriter -VERSION = (2, 1, 0) +VERSION = (2, 1, 1) __title__ = 'Django Render Static' __version__ = '.'.join(str(i) for i in VERSION) diff --git a/render_static/tests/js_tests.py b/render_static/tests/js_tests.py index f27bc04..c4d98c3 100644 --- a/render_static/tests/js_tests.py +++ b/render_static/tests/js_tests.py @@ -3697,6 +3697,35 @@ def test_chained_enum_values(self): self.assertIn('static VALUE1 = new DependentEnum(1, "VALUE1", IndependentEnum.VALUE1, "DependentEnum.VALUE1");', contents) self.assertIn('static VALUE2 = new DependentEnum(2, "VALUE2", IndependentEnum.VALUE0, "DependentEnum.VALUE2");', contents) + @override_settings( + STATIC_TEMPLATES={ + 'ENGINES': [{ + 'BACKEND': 'render_static.backends.StaticDjangoTemplates', + 'OPTIONS': { + 'loaders': [ + ('render_static.loaders.StaticLocMemLoader', { + 'enum_app/test.js': """ +{% enums_to_js enums='render_static.tests.enum_app.models.EnumTester.Color' include_properties="hex,name,value,rgb,label"|split:"," %} +{% enums_to_js enums='render_static.tests.enum_app.models.EnumTester.MapBoxStyle' include_properties="value,name,label,uri,slug,version"|split:"," %} +{% enums_to_js enums='render_static.tests.enum_app.models.EnumTester.AddressRoute' include_properties="name,value,alt"|split:"," %} +""" + }) + ] + }, + }], + } + ) + def test_property_order_determinism_bug131(self): + enum_js = GLOBAL_STATIC_DIR / 'enum_app/test.js' + for _ in range(0,10): + call_command('renderstatic', 'enum_app/test.js') + transpilation = enum_js.read_text() + self.assertIn('constructor (value, name, label, rgb, hex)', transpilation) + self.assertIn('constructor (value, name, label, slug, version, uri, str)', transpilation) + self.assertIn('constructor (value, name, alt, str)', transpilation) + os.remove(enum_js) + + def tearDown(self): pass diff --git a/render_static/transpilers/enums_to_js.py b/render_static/transpilers/enums_to_js.py index 5c66f39..fc7d24a 100644 --- a/render_static/transpilers/enums_to_js.py +++ b/render_static/transpilers/enums_to_js.py @@ -200,36 +200,41 @@ def properties(self, enum: Type[Enum]): """ builtins = [ bltin for bltin in self.builtins_ - if bltin not in self.exclude_properties_ + if bltin == 'value' or bltin not in self.exclude_properties_ ] - if self.include_properties_ is True: + if ( + hasattr(list(enum)[0], 'label') and + 'label' not in builtins and + 'label' not in self.exclude_properties_ and + self.include_properties_ + ): + builtins.append('label') + + props_on_class = [ + str(name) + for name, member in vars(enum).items() if ( - hasattr(list(enum)[0], 'label') and - 'label' not in builtins and - 'label' not in self.exclude_properties_ - ): - builtins.append('label') - props_on_class = [ - str(name) - for name, member in vars(enum).items() - if ( - isinstance(member, property) and - name not in self.exclude_properties_ - and str(name) not in builtins - ) - ] + isinstance(member, property) and + name not in self.exclude_properties_ + and str(name) not in builtins + ) + ] + prop_def_order = [ + *builtins, + *[ + prop for prop in getattr(enum, '_properties_', []) + if prop not in self.exclude_properties_ + and prop not in builtins and prop not in props_on_class + ], + *props_on_class + ] + if self.include_properties_ is True: + self.properties_ = prop_def_order + elif self.include_properties_: self.properties_ = [ - *builtins, - *props_on_class, - # handle enum-properties defined properties - *[ - prop for prop in getattr(enum, '_properties_', []) - if prop not in self.exclude_properties_ - and prop not in builtins and prop not in props_on_class - ] + prop for prop in prop_def_order + if prop in self.include_properties_ or prop == 'value' ] - elif self.include_properties_: - self.properties_ = list({*self.include_properties_, 'value'}) else: self.properties_ = builtins