<commit_before>"""Collections contain content documents and blueprints."""

from . import documents
from . import messages
from grow.common import structures
from grow.common import utils
from grow.pods import locales
import json
import operator
import os

_all = '__no-locale'


class Error(Exception):
  pass


class CollectionNotEmptyError(Error):
  pass


class BadCollectionNameError(Error, ValueError):
  pass


class CollectionDoesNotExistError(Error, ValueError):
  pass


class CollectionExistsError(Error):
  pass


class BadFieldsError(Error, ValueError):
  pass


class NoLocalesError(Error):
  pass


class Collection(object):

  def __init__(self, pod_path, _pod):
    utils.validate_name(pod_path)
    self.pod = _pod
    self.collection_path = pod_path.lstrip('/content')
    self.pod_path = pod_path
    self._default_locale = _pod.podspec.default_locale
    self._blueprint_path = os.path.join(self.pod_path, '_blueprint.yaml')

  def __repr__(self):
    return '<Collection "{}">'.format(self.collection_path)

  @classmethod
  def list(cls, pod):
    # TODO: Implement "depth" argument on pod.list_dir and use.
    paths = pod.list_dir('/content/')
    clean_paths = set()
    for path in paths:
      parts = path.split('/')
      if len(parts) >= 2:  # Disallow files in root-level /content/ dir.
        clean_paths.add(os.path.join('/content', parts[0]))
    return [cls(pod_path, _pod=pod) for pod_path in clean_paths]

  def exists(self):
    return self.pod.file_exists(self._blueprint_path)

  def create_from_message(self, message):
    if self.exists():
      raise CollectionExistsError('{} already exists.'.format(self))
    self.update_from_message(message)
    return self

  @classmethod
  def get(cls, collection_path, _pod):
    collection = cls(collection_path, _pod)
    if not collection.exists():
      message = '{} does not exist.'.format(collection)
      raise CollectionDoesNotExistError(message)
    return collection

  def get_doc(self, pod_path, locale=None):
    doc = documents.Document(pod_path, locale=locale, _pod=self.pod,
                             _collection=self)
    if not doc.exists():
      message = '{} does not exist.'.format(doc)
      raise documents.DocumentDoesNotExistError(message)
    return doc

  @property
  @utils.memoize
  def yaml(self):
    result = utils.parse_yaml(self.pod.read_file(self._blueprint_path))
    if result is None:
      return {}
    return result

  def list_categories(self):
    return self.yaml.get('categories')

  @property
  def title(self):
    return self.yaml.get('title')

  @property
  def root(self):
    return self.yaml.get('root')

  def delete(self):
    if len(self.list_docs(include_hidden=True)):
      text = 'Collections that are not empty cannot be deleted.'
      raise CollectionNotEmptyError(text)
    self.pod.delete_file(self._blueprint_path)

  def update_from_message(self, message):
    if not message.fields:
      raise BadFieldsError('Fields are required to create a collection.')
    fields = json.loads(message.fields)
    fields = utils.dump_yaml(fields)<commit_msg>Be more lenient with missing blueprint files.<commit_after>"""Collections contain content documents and blueprints."""

from . import documents
from . import messages
from grow.common import structures
from grow.common import utils
from grow.pods import locales
import json
import operator
import os

_all = '__no-locale'


class Error(Exception):
  pass


class CollectionNotEmptyError(Error):
  pass


class BadCollectionNameError(Error, ValueError):
  pass


class CollectionDoesNotExistError(Error, ValueError):
  pass


class CollectionExistsError(Error):
  pass


class BadFieldsError(Error, ValueError):
  pass


class NoLocalesError(Error):
  pass


class Collection(object):

  def __init__(self, pod_path, _pod):
    utils.validate_name(pod_path)
    self.pod = _pod
    self.collection_path = pod_path.lstrip('/content')
    self.pod_path = pod_path
    self._default_locale = _pod.podspec.default_locale
    self._blueprint_path = os.path.join(self.pod_path, '_blueprint.yaml')

  def __repr__(self):
    return '<Collection "{}">'.format(self.collection_path)

  @classmethod
  def list(cls, pod):
    # TODO: Implement "depth" argument on pod.list_dir and use.
    paths = pod.list_dir('/content/')
    clean_paths = set()
    for path in paths:
      parts = path.split('/')
      if len(parts) >= 2:  # Disallow files in root-level /content/ dir.
        clean_paths.add(os.path.join('/content', parts[0]))
    return [cls(pod_path, _pod=pod) for pod_path in clean_paths]

  def exists(self):
    return self.pod.file_exists(self._blueprint_path)

  def create_from_message(self, message):
    if self.exists():
      raise CollectionExistsError('{} already exists.'.format(self))
    self.update_from_message(message)
    return self

  @classmethod
  def get(cls, collection_path, _pod):
    collection = cls(collection_path, _pod)
    if not collection.exists():
      message = '{} does not exist.'.format(collection)
      raise CollectionDoesNotExistError(message)
    return collection

  def get_doc(self, pod_path, locale=None):
    doc = documents.Document(pod_path, locale=locale, _pod=self.pod,
                             _collection=self)
    if not doc.exists():
      message = '{} does not exist.'.format(doc)
      raise documents.DocumentDoesNotExistError(message)
    return doc

  @property
  @utils.memoize
  def yaml(self):
    if not self.exists():
      return {}
    result = utils.parse_yaml(self.pod.read_file(self._blueprint_path))
    if result is None:
      return {}
    return result

  def list_categories(self):
    return self.yaml.get('categories')

  @property
  def title(self):
    return self.yaml.get('title')

  @property
  def root(self):
    return self.yaml.get('root')

  def delete(self):
    if len(self.list_docs(include_hidden=True)):
      text = 'Collections that are not empty cannot be deleted.'
      raise CollectionNotEmptyError(text)
    self.pod.delete_file(self._blueprint_path)

  def update_from_message(self, message):
    if not message.fields:
      raise BadFieldsError('Fields are required to create a collection.')
    fields = json.loads(message.fields)
    fields = utils.dump_yaml(fields)
{'fraction_non_alphanumeric': 0.10617637695001592, 'fraction_numerical': 0.0006367398917542184, 'mean_word_length': 3.72406015037594, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '3725311', 'n_tokens_mistral': 1925, 'n_tokens_neox': 1895, 'n_words': 481}