summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/ext
Commit message (Collapse)AuthorAgeFilesLines
* - flake8 for lib passesMike Bayer2019-01-052-4/+3
| | | | Change-Id: I0d7f5105f838a0275f3c240441bdcdc9ae7444d0
* - imports in lib pass flake8Mike Bayer2019-01-051-11/+0
| | | | Change-Id: Ia661822e9d1792da8f965fe3cbb00cce288c8739
* flake8 refactor - extMike Bayer2019-01-057-102/+111
| | | | | | | | | | | | A full rewrite of all imports and pep8 formatting using zimports, black, commits are broken into sections. Directories included in this commit: lib/sqlalchemy/ext/ Change-Id: I3dd7aed3f42675e9ada64446ffd2758db7c3bc93 (cherry picked from commit 0716a292e03040ad4f96b890691b9e2c888ec11d)
* partial cherry-pick of master flake8. clean cherrypick for lib and test,Mike Bayer2019-01-052-6/+2
| | | | | | | manually merged exaples. Change-Id: I9532d3b13d13f2769e6ca48eea23dd7d4041f68f (cherry picked from commit e3bdd80c6661c0e95fb67998c57540be667ce761)
* - do a broken zimports run on libMike Bayer2019-01-0514-93/+118
|
* step 1, straight black -l 79 runMike Bayer2019-01-0516-615/+937
| | | | includes adjustment to setup.py to recognize __version__ correctly
* "left" -> "accidentally placed at"Mike Bayer2018-12-021-2/+2
| | | | | | | | | | | | since "left" is kind of ambiguous, use more explicit terminology here. Also update the test to use a positive assertion that the warning is emitted; quote the attribute name. Change-Id: Ic2284c200a26b32b2da063cfaf6d59547309d587 References: https://github.com/zzzeek/sqlalchemy/pull/488 (cherry picked from commit eacb31a89fe883edd0ada7f2724239c1f8c5b685)
* Warn for lower-case column attribute on declarativeMike Bayer2018-11-261-0/+14
| | | | | | | | | | A warning is emitted in the case that a :func:`.column` object is applied to a declarative class, as it seems likely this intended to be a :class:`.Column` object. Fixes: #4374 Change-Id: I2e617ef65547162e3ba6587c168548ad0cf6203d (cherry picked from commit 6ec40eca1a03a9156ee82f3ce75850778220b39e)
* Add missing index method to _AssociationList.Chris Macklin2018-10-311-0/+3
| | | | | | | | | Added missing ``.index()`` method to list-based association collections in the association proxy extension. Change-Id: Ice81dc4bcccd520638c5bc9a0f8bb2027946c846 Pull-request: https://github.com/zzzeek/sqlalchemy/pull/485 (cherry picked from commit 1c3b2d71863f6aefbc060798c2f50d1e029feef1)
* Move pk on single-inh subclass check below conflict resolution checkTom Manderson2018-10-301-5/+5
| | | | | | | | | | | | | The column conflict resolution technique discussed at :ref:`declarative_column_conflicts` is now functional for a :class:`.Column` that is also a primary key column. Previously, a check for primary key columns declared on a single-inheritance subclass would occur before the column copy were allowed to pass. Fixes: #4352 Change-Id: Id4c025da53c28e58db6b549fe398f25f8a90d355 Pull-request: https://github.com/zzzeek/sqlalchemy/pull/483 (cherry picked from commit 3ed79a5c18c14d842280805d1dae8a9c99ec8f18)
* Add warning to hybrid property expression and fixup crosslinksJames Owen2018-10-301-1/+29
| | | | (cherry picked from commit 681bd7eb8876c8b83912b8307b2fc7500a11e6f0)
* Check more specifically for hybrid attr and not mapped propertyMike Bayer2018-10-201-1/+2
| | | | | | | | | | | Fixed regression caused by :ticket:`4326` in version 1.2.12 where using :class:`.declared_attr` with a mixin in conjunction with :func:`.orm.synonym` would fail to map the synonym properly to an inherited subclass. Fixes: #4350 Change-Id: Ib2a9b6a125a2ac7c7ff80201746b7f10e5596226 (cherry picked from commit 9335c24d6c98033f4aa1ceafd23a70b88c8ae811)
* - pep8 cleanupMike Bayer2018-08-271-3/+1
| | | | | Change-Id: I1d6eaf91c069bd5dd55a40ddd38e2f440b259fea (cherry picked from commit d3dee71c24eabf60e67ecbc6b42d31a38d493105)
* Include Session._query_cls as part of the cache keyMike Bayer2018-08-261-4/+17
| | | | | | | | | | | Fixed issue where :class:`.BakedQuery` did not include the specific query class used by the :class:`.Session` as part of the cache key, leading to incompatibilities when using custom query classes, in particular the :class:`.ShardedQuery` which has some different argument signatures. Fixes: #4328 Change-Id: I829c2a8b09c91e91c8dc8ea5476c0d7aa47028bd (cherry picked from commit c09b07fbb36ac288d32221349b019b490efc9ff3)
* Unwrap Proxy objects when scanning declared_attrMike Bayer2018-08-231-3/+13
| | | | | | | | | | | | | Fixed bug where the declarative scan for attributes would receive the expression proxy delivered by a hybrid attribute at the class level, and not the hybrid attribute itself, when receiving the descriptor via the ``@declared_attr`` callable on a subclass of an already-mapped class. This would lead to an attribute that did not report itself as a hybrid when viewed within :attr:`.Mapper.all_orm_descriptors`. Fixes: #4326 Change-Id: I582d03f05c3768b3344f93e3791240e9e69b9d1e (cherry picked from commit 626356842d77d4ec6427b3bfc04bdff93d24d246)
* Accommodate for classically mapped base classes in declarativeMike Bayer2018-08-171-8/+45
| | | | | | | | | | | | | | | | Fixed issue in previously untested use case, allowing a declarative mapped class to inherit from a classically-mapped class outside of the declarative base, including that it accommodates for unmapped intermediate classes. An unmapped intermediate class may specify ``__abstract__``, which is now interpreted correctly, or the intermediate class can remain unmarked, and the classically mapped base class will be detected within the hierarchy regardless. In order to anticipate existing scenarios which may be mixing in classical mappings into existing declarative hierarchies, an error is now raised if multiple mapped bases are detected for a given class. Fixes: #4321 Change-Id: I8604ecfd170d2589d9d1b1c87ba303762071fc30 (cherry picked from commit 4c931b2ec7e0f09ac8c3ebe28c794f5858d54efb)
* Do some pep8 and other cruft removal around association proxyMike Bayer2018-08-011-11/+13
| | | | | Change-Id: I33130022a7e223318b65388620828d539f6dacfd (cherry picked from commit 65469442ad30b97d5901347e0a5a64f3179f765d)
* Ensure BakedQuery is cloned before we add options to itMike Bayer2018-06-261-0/+7
| | | | | | | | | | | Fixed bug in new polymorphic selectin loading where the BakedQuery used internally would be mutated by the given loader options, which would both inappropriately mutate the subclass query as well as carry over the effect to subsequent queries. Change-Id: Iaceecb50557f78484d09e55b3029a0483dfe873f Fixes: #4286 (cherry picked from commit f243c00dda1484da97e706b7237670cdce6f10b9)
* Add Query.lazy_load_from attribute for shardingMike Bayer2018-06-042-2/+5
| | | | | | | | | | | | | | | | | | | Added new attribute :attr:`.Query.lazy_loaded_from` which is populated with an :class:`.InstanceState` that is using this :class:`.Query` in order to lazy load a relationship. The rationale for this is that it serves as a hint for the horizontal sharding feature to use, such that the identity token of the state can be used as the default identity token to use for the query within id_chooser(). Also repaired an issue in the :meth:`.Result.with_post_criteria` method added in I899808734458e25a023142c2c5bb37cbed869479 for :ticket:`4128` where the "unbake subquery loaders" version was calling the post crtieria functions given the :class:`.Result` as the argument rather than applying them to the :class:`.Query`. Change-Id: I3c0919ce7fd151b80fe2f9b5f99f60df31c2d73d Fixes: #4243 (cherry picked from commit a574b409296ef793cec8e1d00f1f7be48f15325e)
* Mutex on _CONFIGURE_MUTEX in automap.prepare()Mike Bayer2018-05-281-42/+48
| | | | | | | | | | | | | Fixed a race condition which could occur if automap :meth:`.AutomapBase.prepare` were used within a multi-threaded context against other threads which may call :func:`.configure_mappers` as a result of use of other mappers. The unfinished mapping work of automap is particularly sensitive to being pulled in by a :func:`.configure_mappers` step leading to errors. Change-Id: I6d36df6639bf5cb8f137187dff68f386f5e84f88 Fixes: #4266 (cherry picked from commit 2ac7cad7179ff594d8bb3df9856c891bf4e51097)
* Change query._identity_lookup into a normal instance methodMike Bayer2018-05-161-13/+8
| | | | | | | | | | | | | Fixed regression in 1.2.7 caused by :ticket:`4228`, which itself was fixing a 1.2-level regression, where the ``query_cls`` callable passed to a :class:`.Session` was assumed to be a subclass of :class:`.Query` with class method availability, as opposed to an arbitrary callable. In particular, the dogpile caching example illustrates ``query_cls`` as a function and not a :class:`.Query` subclass. Change-Id: I3f86fcb12a6a9a89aa308b335e75c25969bcc30e Fixes: #4256 (cherry picked from commit 3fa38a1a2313b4644daa431d629394d6bb14497a)
* Merge existing query params in baked lazy loadMike Bayer2018-05-161-3/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Corrected backport, was supposed to be in 1.2.5 however never got backported. Fixed a long-standing regression that occurred in version 1.0, which prevented the use of a custom :class:`.MapperOption` that alters the _params of a :class:`.Query` object for a lazy load, since the lazy loader itself would overwrite those parameters. This applies to the "temporal range" example on the wiki. Note however that the :meth:`.Query.populate_existing` method is now required in order to rewrite the mapper options associated with an object already loaded in the identity map. As part of this change, a custom defined :class:`.MapperOption` will now cause lazy loaders related to the target object to use a non-baked query by default unless the :meth:`.MapperOption._generate_cache_key` method is implemented. In particular, this repairs one regression which occured when using the dogpile.cache "advanced" example, which was not returning cached results and instead emitting SQL due to an incompatibility with the baked query loader; with the change, the ``RelationshipCache`` option included for many releases in the dogpile example will disable the "baked" query altogether. Note that the dogpile example is also modernized to avoid both of these issues as part of issue :ticket:`4258`. This is a cherry-pick / squash from: 4a31c30fa5ebd6af0e72937b21b2e5ee79e12631 2e46f73f35b9036287f5f567c09a8cb786fe5fd3 b9f428a589a1718efa20e5555be45ae3f767e89e Change-Id: I899808734458e25a023142c2c5bb37cbed869479 Fixes: #4128
* Use identity_token for refresh(), unexpire, undeferMike Bayer2018-05-111-1/+3
| | | | | | | | | | | | | The horizontal sharding extension now makes use of the identity token added to ORM identity keys as part of :ticket:`4137`, when an object refresh or column-based deferred load or unexpiration operation occurs. Since we know the "shard" that the object originated from, we make use of this value when refreshing, thereby avoiding queries against other shards that don't match this object's identity in any case. Change-Id: Ib91637a65d94ace7405998b8410d62944a83f2eb Fixes: #4247 (cherry picked from commit 4b71933489cae21ad94b71b0bc7271c075ad0dda)
* Refactor "get" to allow for pluggable identity token schemesMike Bayer2018-04-202-21/+57
| | | | | | | | | | | | | | | | Fixed regression in 1.2 within sharded query feature where the new "identity_token" element was not being correctly considered within the scope of a lazy load operation, when searching the identity map for a related many-to-one element. The new behavior will allow for making use of the "id_chooser" in order to determine the best identity key to retrieve from the identity map. In order to achieve this, some refactoring of 1.2's "identity_token" approach has made some slight changes to the implementation of ``ShardedQuery`` which should be noted for other derivations of this class. Change-Id: I04fa60535deec2d0cdec89f602935dfebeb9eb9d Fixes: #4228 (cherry picked from commit 43f278356d94b5342a1020a9a97feea0bb7cd88f)
* Don't warn for mixin-based __table_args__, __mapper_args__ declared_attrMike Bayer2018-03-211-2/+3
| | | | | | | | | | | | | Removed a warning that would be emitted when calling upon ``__table_args__``, ``__mapper_args__`` as named with a ``@declared_attr`` method, when called from a non-mapped declarative mixin. Calling these directly is documented as the approach to use when one is overidding one of these methods on a mapped class. The warning still emits for regular attribute names. Change-Id: Iae7ed0bd625a2c163c910aa777cef4779128580a Fixes: #4221 (cherry picked from commit 37955a52995cdbb66a9d5835c20ee58fb98ddffc)
* Ignore non-primary mappers within mutable instrumentationMike Bayer2018-03-121-0/+4
| | | | | | | | | | | | | Fixed bug where using :meth:`.Mutable.associate_with` or :meth:`.Mutable.as_mutable` in conjunction with a class that has non- primary mappers set up with alternatively-named attributes would produce an attribute error. Since non-primary mappers are not used for persistence, the mutable extension now excludes non-primary mappers from its instrumentation steps. Change-Id: I2630d9f771a171aece03181ccf9159885f68f25e Fixes: #4215 (cherry picked from commit 0fd508ad32a6f94653757a5ae10c1eae14e099fc)
* Default to using current mapped class as owner if none foundMike Bayer2018-02-201-1/+6
| | | | | | | | | | | Repaired regression caused in 1.2.3 and 1.1.16 regarding association proxy objects, revising the approach to :ticket:`4185` when calculating the "owning class" of an association proxy to default to choosing the current class if the proxy object is not directly associated with a mapped class, such as a mixin. Change-Id: I87d0ac09f695dc285bd4bbe0a547f1d5ce23e068 Fixes: #4185
* Search through mapper superclass hierarchy for ownerMike Bayer2018-02-091-13/+35
| | | | | | | | | | | | | | | | Fixed regression caused by fix for issue :ticket:`4116` affecting versions 1.2.2 as well as 1.1.15, which had the effect of mis-calculation of the "owning class" of an :class:`.AssociationProxy` as the ``NoneType`` class in some declarative mixin/inheritance situations as well as if the association proxy were accessed off of an un-mapped class. The "figure out the owner" logic has been replaced by an in-depth routine that searches through the complete mapper hierarchy assigned to the class or subclass to determine the correct (we hope) match; will not assign the owner if no match is found. An exception is now raised if the proxy is used against an un-mapped instance. Change-Id: I611b590df2babe077ce6c19bea89e84251d1a7f4 Fixes: #4185
* Rework synonym, synonym_for documentationMike Bayer2018-01-241-11/+26
| | | | | | | | The map_column example was incorrect, and overall the purpose of this parameter as well as that of synonym_for was not explained; examples added along with more encouragement to use hybrids. Change-Id: I20bd286f541f798daa81fa598c0f31db1f5aa6ed
* happy new yearMike Bayer2018-01-1215-15/+15
| | | | Change-Id: I3ef36bfd0cb0ba62b3123c8cf92370a43156cf8f
* Check for the endmost target when chaining contains()Mike Bayer2018-01-021-0/+1
| | | | | | | | | | | | Fixed regression in association proxy due to :ticket:`3769` (allow for chained any() / has()) where contains() against an association proxy chained in the form (o2m relationship, associationproxy(m2o relationship, m2o relationship)) would raise an error regarding the re-application of contains() on the final link of the chain. Change-Id: Iea51ce84c2c5a332416fff10b1ba0e676cf0bad7 Fixes: #4150
* Add an identity_token to the identity keyMike Bayer2017-12-221-4/+30
| | | | | | | | | For the purposes of assisting with sharded setups, add a new member to the identity key that can be customized. this allows sharding across databases where the primary key space is shared. Change-Id: Iae3909f5d4c501b62c10d0371fbceb01abda51db Fixes: #4137
* Add baked.Result.with_post_criteria methodMike Bayer2017-11-122-15/+56
| | | | | | | | | | | | | Added new method :meth:`.baked.Result.with_post_criteria` to baked query system, allowing non-SQL-modifying transformations to take place after the query has been pulled from the cache. Among other things, this method can be used with :class:`.horizontal_shard.ShardedQuery` to set the shard identifier. :class:`.horizontal_shard.ShardedQuery` has also been modified such that its :meth:`.ShardedQuery.get` method interacts correctly with that of :class:`.baked.Result`. Change-Id: I04630c683240abbb4b99f0510a1a3dcb564815b4 Fixes: #4135
* - add notes that @comparator and @expression don't go together.Mike Bayer2017-10-301-0/+8
| | | | Change-Id: I3fb366f8b49454453e4b6dada565c24c5ccb975e
* Resolve AliasedClass when determining owning class of association proxyMike Bayer2017-10-201-1/+12
| | | | | | | | | | Fixed bug where the association proxy would inadvertently link itself to an :class:`.AliasedClass` object if it were called first with the :class:`.AliasedClass` as a parent, causing errors upon subsequent usage. Change-Id: I9161bab67766bb75d73ca54d712ad1cad6de40dc Fixes: #4116
* Warnings for @declared_attr.cascadingticket_4091Mike Bayer2017-09-262-8/+52
| | | | | | | | | | | | | | | | | | | | | A warning is emitted if a subclass attempts to override an attribute that was declared on a superclass using ``@declared_attr.cascading`` that the overridden attribute will be ignored. This use case cannot be fully supported down to further subclasses without more complex development efforts, so for consistency the "cascading" is honored all the way down regardless of overriding attributes. A warning is emitted if the ``@declared_attr.cascading`` attribute is used with a special declarative name such as ``__tablename__``, as this has no effect. Ensure that documenation refers to the current inconsistency that __tablename__ can be overridden by subclasses however @declared_attr.cascading cannot. Fixes: #4091 Fixes: #4092 Change-Id: I3aecdb2f99d408e404a1223f5ad86ae3c7fdf036
* Include missing import in exampleMichael Stewart2017-06-301-0/+1
|
* Support AssociationProxy any() / has() / contains() to another AssociationProxyMike Bayer2017-06-121-36/+68
| | | | | | | | | | | | | | | | | | | The :meth:`.AssociationProxy.any`, :meth:`.AssociationProxy.has` and :meth:`.AssociationProxy.contains` comparison methods now support linkage to an attribute that is itself also an :class:`.AssociationProxy`, recursively. After some initial attempts it's clear that the any() / has() of AssociationProxy needed to be reworked into a generic _criterion_exists() to allow this to work recursively without excess complexity. For the case of the multi-linked associationproxy, the usual checks of "any()" / "has()" correctness simply don't take place; for a single-link association proxy the error checking logic that takes place in relationship() has been ported to the local any() / has() methods. Change-Id: Ic5aed2a4e910b8138a737d215430113c31cce856 Fixes: #3769
* Warn when declared_attr.cascading detected on mapped classMike Bayer2017-06-062-0/+13
| | | | | | | | | | | | | | A warning is emitted if the :attr:`.declared_attr.cascading` modifier is used with a declarative attribute that is itself declared on a class that is to be mapped, as opposed to a declarative mixin class or ``__abstract__`` class. The :attr:`.declared_attr.cascading` modifier currently only applies to mixin/abstract classes. Also add a test for @declared_attr.cascading when used on an attribute on __abstract__. Change-Id: Ib1b9dbe373e8be1cf24eadfed224a8988b3cd95d Fixes: #3847
* Implement in-place mutation operators for MutableSet, MutableListMike Bayer2017-06-051-0/+20
| | | | | | | | | | | Implemented in-place mutation operators ``__ior__``, ``__iand__``, ``__ixor__`` and ``__isub__`` for :class:`.mutable.MutableSet` and ``__iadd__`` for :class:`.mutable.MutableList` so that change events are fired off when these mutator methods are used to alter the collection. Change-Id: Ib357a96d3b06c5deb6b53eb304a8b9f1dc9e9ede Fixes: #3853
* selectin polymorphic loadingMike Bayer2017-06-051-4/+7
| | | | | | | | | | | | | Added a new style of mapper-level inheritance loading "polymorphic selectin". This style of loading emits queries for each subclass in an inheritance hierarchy subsequent to the load of the base object type, using IN to specify the desired primary key values. Fixes: #3948 Change-Id: I59e071c6142354a3f95730046e3dcdfc0e2c4de5
* Don't hard-evaluate non-ORM @declared_attr for AbstractConcreteBaseMike Bayer2017-05-261-1/+5
| | | | | | | | | | | | | | | | Fixed bug where using :class:`.declared_attr` on an :class:`.AbstractConcreteBase` where a particular return value were some non-mapped symbol, including ``None``, would cause the attribute to hard-evaluate just once and store the value to the object dictionary, not allowing it to invoke for subclasses. This behavior is normal when :class:`.declared_attr` is on a mapped class, and does not occur on a mixin or abstract class. Since :class:`.AbstractConcreteBase` is both "abstract" and actually "mapped", a special exception case is made here so that the "abstract" behavior takes precedence for :class:`.declared_attr`. Change-Id: I6160ebb3a52c441d6a4b663c8c9bbac6d37fa417 Fixes: #3848
* Add AttributeEvents.modifiedMike Bayer2017-05-231-0/+22
| | | | | | | | | | Added new event handler :meth:`.AttributeEvents.modified` which is triggered when the func:`.attributes.flag_modified` function is invoked, which is common when using the :mod:`sqlalchemy.ext.mutable` extension module. Change-Id: Ic152f1d5c53087d780b24ed7f1f1571527b9e8fc Fixes: #3303
* Add new configuration, inspection for baked queriesMike Bayer2017-05-171-6/+26
| | | | | | | | | | Added new flag :paramref:`.Session.enable_baked_queries` to the :class:`.Session` to allow baked queries to be disabled session-wide, reducing memory use. Also added new :class:`.Bakery` wrapper so that the bakery returned by :paramref:`.BakedQuery.bakery` can be inspected. Change-Id: I5657af7a99d2b24c89d6aee1343f432728e3f807
* - give SelectinLoader its own bakery, dont use mapperMike Bayer2017-05-161-1/+2
| | | | | | | | level cache - include SelectinLoader itself in the cache key, though this is currently not critical Change-Id: I8e4bcd579277fbe53d9c7eca3552a0b8ab9d7a39
* Protect against cls weakref becoming NoneMike Bayer2017-05-082-4/+8
| | | | | | | | | | Protected against testing "None" as a class in the case where declarative classes are being garbage collected and new automap prepare() operations are taking place concurrently, very infrequently hitting a weakref that has not been fully acted upon after gc. Change-Id: I32e1dfc5ac46bac4127fe808cfd18368e2fad9dd
* Call proxied collection before invoking creator in associationlist.append()Mike Bayer2017-04-281-1/+2
| | | | | | | | | | | | Improved the association proxy list collection so that premature autoflush against a newly created association object can be prevented in the case where ``list.append()`` is being used, and a lazy load would be invoked when the association proxy accesses the endpoint collection. The endpoint collection is now accessed first before the creator is invoked to produce the association object. Change-Id: I008a6dbdfe5b1c0dfd02189c3d954d83a65f3fc5 Fixes: #3941
* Use baked lazyloading by defaultMike Bayer2017-04-131-109/+50
| | | | | | | | | | | | | The ``lazy="select"`` loader strategy now makes used of the :class:`.BakedQuery` query caching system in all cases. This removes most overhead of generating a :class:`.Query` object and running it into a :func:`.select` and then string SQL statement from the process of lazy-loading related collections and objects. The "baked" lazy loader has also been improved such that it can now cache in most cases where query load options are used. Change-Id: Ic96792fffaa045ae9aa0a4657d6d29235d3efb85 Fixes: #3954
* Ensure we check that SQL expression has an .info attributeMike Bayer2017-04-041-1/+2
| | | | | | | | | | Fixed regression released in 1.1.8 due to :ticket:`3950` where the deeper search for information about column types in the case of a "schema type" or a :class:`.TypeDecorator` would produce an attribute error if the mapping also contained a :obj:`.column_property`. Change-Id: I38254834d3d79c9b339289a8163eb4789ec4c931 Fixes: #3956
* Track SchemaEventTarget types in as_mutable()Mike Bayer2017-03-301-1/+19
| | | | | | | | | | | | | | Fixed bug in :mod:`sqlalchemy.ext.mutable` where the :meth:`.Mutable.as_mutable` method would not track a type that had been copied using :meth:`.TypeEngine.copy`. This became more of a regression in 1.1 compared to 1.0 because the :class:`.TypeDecorator` class is now a subclass of :class:`.SchemaEventTarget`, which among other things indicates to the parent :class:`.Column` that the type should be copied when the :class:`.Column` is. These copies are common when using declarative with mixins or abstract classes. Change-Id: Ib04df862c58263185dbae686c548fea3e12c46f1 Fixes: #3950