class TestTimestampVersion(TempEnvironmentHelper): def setup(self): super(TestTimestampVersion, self).setup() self.v = TimestampVersion() # Create a bunch of files with known mtimes self.create_files(['in', 'dep']) self.source_max = now = self.setmtime('dep') self.setmtime('in', mtime=now - 100) self.bundle = self.mkbundle('in', depends=('dep'), output='out') def test_with_hunk(self): # If a hunk indicates call during a build, the output file is ignored, # and the versioner looks at the source files. self.create_files([self.bundle.output]) self.setmtime(self.bundle.output, mtime=self.source_max + 100) hunk = MemoryHunk('foo') assert self.v.determine_version(self.bundle, self.env, hunk) == int(self.source_max) def test_no_placeholder(self): # If output name contains no placeholder, the output file will be used # to determine the timestamp. self.create_files(['out']) self.setmtime('out', mtime=self.source_max + 100) assert self.v.determine_version(self.bundle, self.env, None) == int(self.source_max + 100) # What if the output file does not exist? (this should not happen, right?) self.unlink('out') assert_raises(OSError, self.v.determine_version, self.bundle, self.env, None) def test_with_placeholder(self): # If output name contains a placeholder, only source files can be used. self.bundle.output = 'out-%(version)s' assert self.v.determine_version(self.bundle, self.env, None) == int(self.source_max) # If any source file is missing, the updater cannot do its job. self.unlink('dep') assert_raises(VersionIndeterminableError, self.v.determine_version, self.bundle, self.env, None) def test_outputfile_timestamp(self): """The timestamp versioner ensures that an output file after being built has an mtime that reflects the version (the maximum mtime of the sources), NOT the current system time. """ # Make sure that all source files have dates in the past, so we don't # pass this test by accident. source_max = self.setmtime('in', mod=-100) bundle = self.mkbundle('in', output='out') # Make sure our versioner is used self.env.versions = self.v bundle.build(force=True) # Only expect second precision assert int(os.path.getmtime(self.path('out'))) == int(source_max)
def setup(self): super(TestTimestampVersion, self).setup() self.v = TimestampVersion() # Create a bunch of files with known mtimes self.create_files(['in', 'dep']) self.source_max = now = self.setmtime('dep') self.setmtime('in', mtime=now-100) self.bundle = self.mkbundle('in', depends=('dep'), output='out')
def check_timestamps(self, bundle, env, o_modified=None): from bundle import Bundle, is_url from webassets.version import TimestampVersion if not o_modified: try: resolved_output = bundle.resolve_output(env) except BundleError: # This exception will occur when the bundle output has # placeholder, but a version cannot be found. If the # user has defined a manifest, this will just be the first # build. Return True to let it happen. # However, if no manifest is defined, raise an error, # because otherwise, this updater would always return True, # and thus not do its job at all. if env.manifest is None: raise BuildError( ( "%s uses a version placeholder, and you are " 'using "%s" versions. To use automatic ' "building in this configuration, you need to " "define a manifest." % (bundle, env.versions) ) ) return True try: o_modified = TimestampVersion.get_timestamp(resolved_output) except OSError: # If the output file does not exist, we'll have to rebuild return True # Recurse through the bundle hierarchy. Check the timestamp of all # the bundle source files, as well as any additional # dependencies that we are supposed to watch. for iterator, result in ( (lambda e: map(lambda s: s[1], bundle.resolve_contents(e)), True), (bundle.resolve_depends, SKIP_CACHE), ): for item in iterator(env): if isinstance(item, Bundle): nested_result = self.check_timestamps(item, env, o_modified) if nested_result: return nested_result elif not is_url(item): try: s_modified = TimestampVersion.get_timestamp(item) except OSError: # If a file goes missing, always require # a rebuild. return result else: if s_modified > o_modified: return result return False
def check_timestamps(self, bundle, ctx, o_modified=None): from .bundle import Bundle from webassets.version import TimestampVersion if not o_modified: try: resolved_output = bundle.resolve_output(ctx) except BundleError: # This exception will occur when the bundle output has # placeholder, but a version cannot be found. If the # user has defined a manifest, this will just be the first # build. Return True to let it happen. # However, if no manifest is defined, raise an error, # because otherwise, this updater would always return True, # and thus not do its job at all. if ctx.manifest is None: raise BuildError( ('%s uses a version placeholder, and you are ' 'using "%s" versions. To use automatic ' 'building in this configuration, you need to ' 'define a manifest.' % (bundle, ctx.versions))) return True try: o_modified = TimestampVersion.get_timestamp(resolved_output) except OSError: # If the output file does not exist, we'll have to rebuild return True # Recurse through the bundle hierarchy. Check the timestamp of all # the bundle source files, as well as any additional # dependencies that we are supposed to watch. from webassets.bundle import wrap for iterator, result in ( (lambda e: map(lambda s: s[1], bundle.resolve_contents(e)), True), (bundle.resolve_depends, SKIP_CACHE)): for item in iterator(ctx): if isinstance(item, Bundle): nested_result = self.check_timestamps( item, wrap(ctx, item), o_modified) if nested_result: return nested_result elif not is_url(item): try: s_modified = TimestampVersion.get_timestamp(item) except OSError: # If a file goes missing, always require # a rebuild. return result else: if s_modified > o_modified: return result return False
class TestTimestampVersion(TempEnvironmentHelper): def setup(self): super(TestTimestampVersion, self).setup() self.v = TimestampVersion() # Create a bunch of files with known mtimes self.create_files(['in', 'dep']) self.source_max = now = self.setmtime('dep') self.setmtime('in', mtime=now-100) self.bundle = self.mkbundle('in', depends=('dep'), output='out') def test_with_hunk(self): # If a hunk indicates call during a build, the output file is ignored, # and the versioner looks at the source files. self.create_files([self.bundle.output]) self.setmtime(self.bundle.output, mtime=self.source_max+100) hunk = MemoryHunk('foo') assert self.v.determine_version( self.bundle, self.env, hunk) == int(self.source_max) def test_no_placeholder(self): # If output name contains no placeholder, the output file will be used # to determine the timestamp. self.create_files(['out']) self.setmtime('out', mtime=self.source_max+100) assert self.v.determine_version( self.bundle, self.env, None) == int(self.source_max+100) # What if the output file does not exist? (this should not happen, right?) self.unlink('out') assert_raises(OSError, self.v.determine_version, self.bundle, self.env, None) def test_with_placeholder(self): # If output name contains a placeholder, only source files can be used. self.bundle.output = 'out-%(version)s' assert self.v.determine_version( self.bundle, self.env, None) == int(self.source_max) # If any source file is missing, the updater cannot do it's job. self.unlink('dep') assert_raises(VersionIndeterminableError, self.v.determine_version, self.bundle, self.env, None) def test_outputfile_timestamp(self): """The timestamp versioner ensures that an output file after being built has an mtime that reflects the version (the maximum mtime of the sources), NOT the current system time. """ # Make sure that all source files have dates in the past, so we don't # pass this test by accident. source_max = self.setmtime('in', mod=-100) bundle = self.mkbundle('in', output='out') # Make sure our versioner is used self.env.versions = self.v bundle.build(force=True) # Only expect second precision assert int(os.path.getmtime(self.path('out'))) == int(source_max)