In a processes that generates many images, you could run into a
cituation with too man files being open. This results in:
IOError: [Errno 24] Too many open files
StrategyWrapper was unnecessarily implemented as a LazyObject
and it triggered a bug in Django (issue 21840).
Changing the lazy object to a function works just as well and
bypasses the bug.
Changed my mind about 04aa72c1f9. It's
just a better description, even if different strategies can change the
behavior so it isn't really very cache-like.
This allows a sensible specialized interface for source groups, but also
for ImageKit to interact with specs using the generalized image
generator interface.
Everything for dealing with files should be part of
GeneratedImageCacheFile--not the generator. The fact that
GeneratedImageCacheFile can get this information (storage, filename,
etc.) is a convenience so that the user only has to define one class
(the generator) to fully specify their functionality, but handling the
cache file is not part of the core responsibility of the generator.
This is also the reason for the renaming of `get_filename` and `storage`
to `cache_file_name` and `cache_file_storage`: the generator is just as
useful for those who want to generate persistent files. But the original
attribute names didn't indicate that they were used only for cache
files. The new ones do, and don't preclude the addition of other
versions that would be used by another `File` subclass for specifying
file names or storage classes.
Previously, we were relying on `__init__`'s arguments to recreate specs.
Now we do it the proper way, using the dict returned by `__getstate__`
(which may or may not include those arguments).
Previously, we had two places where we were passing kwargs that affected
the image generation: the ImageSpec constructor and the generate method.
These were essentially partial applications. With this commit, there's
only one partial application (when the spec is instantiated), and the
generate method is called without arguments. Therefore, specs can now
be treated as generic generators whose constructors just happen to
accept a source_file.
The registry module splits the work that specs.SpecRegistry
used to do into two classes: GeneratorRegistry and
SourceGroupRegistry. These two registries are wrapped in
Register and Unregister utilities for API convenience.
As mentioned in #167, we want to be forward thinking and allow for a
hypothetical spec supertype which has the same functionality as an image
spec but doesn't require a source file: a generator. To this end, I've
renamed `ImageSpec.apply()` to `ImageSpec.generate()` and extracted
a `GeneratedImageCacheFile` base class from `ImageSpecCacheFile`, which
supports the more general interface of a generator--namely, a
`generate()` method with arbitrary args and kwargs.