<commit_before>"""
Products are persistent changes triggered by Tasks such as a new file
in the local filesystem or a table in a database
"""
import os
from pathlib import Path
from dstools.pipeline.products.Product import Product
from dstools.pipeline.placeholders import StringPlaceholder


class File(Product):
    """A product representing a file in the local filesystem
    """
    IDENTIFIERCLASS = StringPlaceholder

    @property
    def _path_to_file(self):
        return Path(str(self._identifier))

    @property
    def _path_to_stored_source_code(self):
        return Path(str(self._path_to_file) + '.source')

    def fetch_metadata(self):
        # we can safely do this here since this is only run when the file
        # exists
        timestamp = self._path_to_file.stat().st_mtime

        # but we have no control over the stored code, it might be missing
        # so we check
        if self._path_to_stored_source_code.exists():
            stored_source_code = self._path_to_stored_source_code.read_text()
        else:
            stored_source_code = None

        return dict(timestamp=timestamp, stored_source_code=stored_source_code)

    def save_metadata(self):
        # timestamp automatically updates when the file is saved...
        self._path_to_stored_source_code.write_text(self.stored_source_code)

    def exists(self):
        return self._path_to_file.exists()

    def delete(self, force=False):
        # force is not used for this product but it is left for API
        # compatibility
        self.logger.debug(f'Deleting {self._path_to_file}')
        os.remove(self._path_to_file)

    @property
    def name(self):
        return self._path_to_file.with_suffix('').name<commit_msg>File.delete do not crashes if files does not exist<commit_after>"""
Products are persistent changes triggered by Tasks such as a new file
in the local filesystem or a table in a database
"""
import os
from pathlib import Path
from dstools.pipeline.products.Product import Product
from dstools.pipeline.placeholders import StringPlaceholder


class File(Product):
    """A product representing a file in the local filesystem
    """
    IDENTIFIERCLASS = StringPlaceholder

    @property
    def _path_to_file(self):
        return Path(str(self._identifier))

    @property
    def _path_to_stored_source_code(self):
        return Path(str(self._path_to_file) + '.source')

    def fetch_metadata(self):
        # we can safely do this here since this is only run when the file
        # exists
        timestamp = self._path_to_file.stat().st_mtime

        # but we have no control over the stored code, it might be missing
        # so we check
        if self._path_to_stored_source_code.exists():
            stored_source_code = self._path_to_stored_source_code.read_text()
        else:
            stored_source_code = None

        return dict(timestamp=timestamp, stored_source_code=stored_source_code)

    def save_metadata(self):
        # timestamp automatically updates when the file is saved...
        self._path_to_stored_source_code.write_text(self.stored_source_code)

    def exists(self):
        return self._path_to_file.exists()

    def delete(self, force=False):
        # force is not used for this product but it is left for API
        # compatibility
        if self.exists():
            self.logger.debug(f'Deleting {self._path_to_file}')
            os.remove(self._path_to_file)
        else:
            self.logger.debug(f'{self._path_to_file} does not exist '
                              'ignoring...')

    @property
    def name(self):
        return self._path_to_file.with_suffix('').name
{'fraction_non_alphanumeric': 0.07474086197490452, 'fraction_numerical': 0.0, 'mean_word_length': 2.9261241970021414, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4136654', 'n_tokens_mistral': 1050, 'n_tokens_neox': 1026, 'n_words': 307}