gitlabculture
clone your own copy | download snapshot

Snapshots | iceberg

No images in this repository’s iceberg at this time

Inside this repository

models.py
text/x-python

Download raw (4.6 KB)

from utils import make_local_url, debug
from api import ApiCallJson, ApiCallJson, ApiCall, get_commits, get_group, get_projects, get_project, get_tree
import os.path
import markdown
import datetime

STRPTIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'

"""
  - Api Call encoded in the 'model'
  - Possibility to avoid cache

  Model 
    - constructor inserts data from the API
    - way to retreive attributes: data, __getter__ () => key in data return
    - 'get', get on the api Call
"""
class Model (object):
  def __init__ (self, id, parent_id=None, data={}):
    if id:
      self.id = id
    else:
      raise ValueError("Need an id.")

    self.data = data

    if parent_id:
      self.parent_id = parent_id

    self.data = data

  @property
  def api_call (self):
    raise NotImplementedError()

  def get (self, force_call=False):
    data = self.api_call.get(force_call=force_call)

    if data:
      for k, v in data.items():
        self.__setattr__(k, v) 

  def __setattr__ (self, name, value):
    if name == 'data' or name == 'id':
      super().__setattr__(name, value)
    else:
      self.data[name] = value
  
  def __getattr__ (self, name):  
    if name in self.data:
      return self.data[name]
    
    return super().__getattr__(name)

class Collection (object):  
  model = Model

  def __init__ (self, models = []):
    self.models = []

    for model in models:
      self.insert(model)

  def insert (self, model):
    if not isinstance(model, self.model):
      model = self.model(model['id'], data=model)
    
    self.models.append(model)

  def __iter__ (self):
    return iter(self.models)

  def __len__ (self):
    return len(self.models)

class Commit (Model):
  pass
  # @property
  # def api_call (self):
    # return ApiCallJson(['project', self.project_id, 'commits', self.id])

class Project (Model):
  @property
  def links (self):
    # Derive the URL for the project from the name.
    # Split on '.', remove last (filename)
    # Remove first if it is OSP (old naming scheme)
    # TODO: move this to a hook for wider compatibility?
    parts = self.name.split('.')
    path = parts[:-1]
    name = '{}.html'.format(parts[-1])

    if not path:
      # Assume work if no prefix was found
      path = ['work']
    elif path[0] == 'osp':
      path.pop(0)

    return {
      'self': make_local_url(os.path.join(*path, name))
    }

  @property
  def last_activity_at (self):
    if 'last_activity_at' in self.data:
      return datetime.datetime.strptime(self.data['last_activity_at'], STRPTIME_FORMAT)

  @property
  def created_at (self):
    if 'created_at' in self.data:
      return datetime.datetime.strptime(self.data['created_at'], STRPTIME_FORMAT)

  @property
  def commits (self):
    if not hasattr(self, '_commits'):
      call = get_commits(project_id=self.id)
      call.expire_cache_after(self.last_activity_at)
      self._commits = Commits(call.get())
    return self._commits

  @property
  def tree (self):
    if not hasattr(self, '_tree'):
      call = get_tree(project_id=self.id)
      call.expire_cache_after()
      self._tree = Tree(call.get())
    return self._tree

  @property
  def readme (self):
    # Return a readme
    pass

  @property
  def api_call (self):
    return get_project(self.id)

class Projects (Collection):
  model = Project

class Group (Model):
  @property
  def api_call (self):
    return get_group(self.id)

  @property
  def projects (self):
    if not hasattr(self, '_projects'):
      self._projects = Projects(get_projects(self.id).get())
    return self._projects


  def invalidate_cache(self):
    self.api_call.invalidate_cache()
    get_projects(self.id).invalidate_cache()

class Commits (Collection):
  model = Commit

"""
  Wrapper around a folder from the api.
    - can display the foldername
    - an iterator through the contents
"""
# class TreeFolder(object):
#   pass

# class TreeFile():
#   def __init__ (self, name, data):
#     self.name = name
#     self.data = data

#   def __str__ (self):
#     return self.data

# class TreeFileMarkdown(TreeFile):
#   def __str__ (self):
#     return markdown.markdown(self.data)

# class TreeFileImage(TreeFile):
#   def __str__ (self):
#     return self.path

#   def thumbnail(width):
#     pass

class TreeEntry (Model):
  pass

class Tree (Collection):
  model = TreeEntry

# class TreeEntry (object):
#   props = ['id', 'name', 'type', 'path', 'mode', 'project']

#   def __init__ (self, **kwargs):
#     for k in kwargs:
#       if k in self.props:
#         self.__setattr__(k, kwargs[k])

#   def __str__ (self):
#     return self.get()

#   def get (self):
#     print('Trying to load', self.project.id)
#     return raw(self.project.id, self.id).get()