Fixed a too-inclusive .hgignore file as well as some other fixes.
This commit is contained in:
parent
d1e0836d23
commit
3c96dc9cc9
5 changed files with 1340 additions and 1 deletions
15
.hgignore
15
.hgignore
|
|
@ -5,5 +5,18 @@ syntax: glob
|
||||||
|
|
||||||
*.pyc
|
*.pyc
|
||||||
*.swp
|
*.swp
|
||||||
|
*.old
|
||||||
|
*.prof
|
||||||
|
*.orig
|
||||||
|
*.key
|
||||||
*~
|
*~
|
||||||
*#
|
\#*\#
|
||||||
|
game/logs/*
|
||||||
|
game/*.restart
|
||||||
|
game/*.pid
|
||||||
|
game/*.db3
|
||||||
|
docs/sphinx/build/*
|
||||||
|
docs/sphinx/wiki2rest/wiki2html/*
|
||||||
|
docs/sphinx/wiki2rest/rest/*
|
||||||
|
docs/sphinx/wiki2rest/html/*
|
||||||
|
docs/sphinx/wiki2html/*
|
||||||
|
|
|
||||||
288
docs/conf.py
Normal file
288
docs/conf.py
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# evennia documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Fri Mar 30 00:25:21 2012.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath('.'))))
|
||||||
|
from django.core.management import setup_environ
|
||||||
|
from game import settings
|
||||||
|
setup_environ(settings)
|
||||||
|
|
||||||
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'evennia'
|
||||||
|
copyright = u'2012, Author'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = ''
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = ''
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'default'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
#html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'evenniadoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#'preamble': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
|
latex_documents = [
|
||||||
|
('index', 'evennia.tex', u'evennia Documentation',
|
||||||
|
u'Author', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('index', 'evennia', u'evennia Documentation',
|
||||||
|
[u'Author'], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output ------------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
('index', 'evennia', u'evennia Documentation',
|
||||||
|
u'Author', 'evennia', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Epub output ---------------------------------------------------
|
||||||
|
|
||||||
|
# Bibliographic Dublin Core info.
|
||||||
|
epub_title = u'evennia'
|
||||||
|
epub_author = u'Author'
|
||||||
|
epub_publisher = u'Author'
|
||||||
|
epub_copyright = u'2012, Author'
|
||||||
|
|
||||||
|
# The language of the text. It defaults to the language option
|
||||||
|
# or en if the language is not set.
|
||||||
|
#epub_language = ''
|
||||||
|
|
||||||
|
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||||
|
#epub_scheme = ''
|
||||||
|
|
||||||
|
# The unique identifier of the text. This can be a ISBN number
|
||||||
|
# or the project homepage.
|
||||||
|
#epub_identifier = ''
|
||||||
|
|
||||||
|
# A unique identification for the text.
|
||||||
|
#epub_uid = ''
|
||||||
|
|
||||||
|
# A tuple containing the cover image and cover page html template filenames.
|
||||||
|
#epub_cover = ()
|
||||||
|
|
||||||
|
# HTML files that should be inserted before the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_pre_files = []
|
||||||
|
|
||||||
|
# HTML files shat should be inserted after the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_post_files = []
|
||||||
|
|
||||||
|
# A list of files that should not be packed into the epub file.
|
||||||
|
#epub_exclude_files = []
|
||||||
|
|
||||||
|
# The depth of the table of contents in toc.ncx.
|
||||||
|
#epub_tocdepth = 3
|
||||||
|
|
||||||
|
# Allow duplicate toc entries.
|
||||||
|
#epub_tocdup = True
|
||||||
347
src/objects/migrations/0010_converting_attributes.py
Normal file
347
src/objects/migrations/0010_converting_attributes.py
Normal file
|
|
@ -0,0 +1,347 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import DataMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
from src.utils.utils import to_str, to_unicode
|
||||||
|
from src.typeclasses.models import PackedDBobject
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
CTYPEGET = ContentType.objects.get
|
||||||
|
GA = object.__getattribute__
|
||||||
|
SA = object.__setattr__
|
||||||
|
DA = object.__delattr__
|
||||||
|
|
||||||
|
class PackedDict(dict):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of dict that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing dict. The db_store variable
|
||||||
|
is set by Attribute.validate_data() when returned in
|
||||||
|
order to allow custom updates to the dict.
|
||||||
|
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedDict, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items())
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"assign item to this dict"
|
||||||
|
super(PackedDict, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def clear(self, *args, **kwargs):
|
||||||
|
"Custom clear"
|
||||||
|
super(PackedDict, self).clear(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedDict, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def popitem(self, *args, **kwargs):
|
||||||
|
"Custom popitem"
|
||||||
|
super(PackedDict, self).popitem(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def update(self, *args, **kwargs):
|
||||||
|
"Custom update"
|
||||||
|
super(PackedDict, self).update(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
class PackedList(list):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of list that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing list.
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedList, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "[%s]" % ", ".join(str(val) for val in self)
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"Custom setitem that stores changed list to database."
|
||||||
|
super(PackedList, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def append(self, *args, **kwargs):
|
||||||
|
"Custom append"
|
||||||
|
super(PackedList, self).append(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def extend(self, *args, **kwargs):
|
||||||
|
"Custom extend"
|
||||||
|
super(PackedList, self).extend(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def insert(self, *args, **kwargs):
|
||||||
|
"Custom insert"
|
||||||
|
super(PackedList, self).insert(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def remove(self, *args, **kwargs):
|
||||||
|
"Custom remove"
|
||||||
|
super(PackedList, self).remove(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedList, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def reverse(self, *args, **kwargs):
|
||||||
|
"Custom reverse"
|
||||||
|
super(PackedList, self).reverse(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def sort(self, *args, **kwargs):
|
||||||
|
"Custom sort"
|
||||||
|
super(PackedList, self).sort(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
|
||||||
|
def to_attr(data):
|
||||||
|
"""
|
||||||
|
Convert data to proper attr data format before saving
|
||||||
|
|
||||||
|
We have to make sure to not store database objects raw, since
|
||||||
|
this will crash the system. Instead we must store their IDs
|
||||||
|
and make sure to convert back when the attribute is read back
|
||||||
|
later.
|
||||||
|
|
||||||
|
Due to this it's criticial that we check all iterables
|
||||||
|
recursively, converting all found database objects to a form
|
||||||
|
the database can handle. We handle lists, tuples and dicts
|
||||||
|
(and any nested combination of them) this way, all other
|
||||||
|
iterables are stored and returned as lists.
|
||||||
|
|
||||||
|
data storage format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string or number
|
||||||
|
dbobj - a single dbobj
|
||||||
|
iter - any iterable object - will be looped over recursively
|
||||||
|
to convert dbobj->id.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def iter_db2id(item):
|
||||||
|
"""
|
||||||
|
recursively looping through stored iterables, replacing objects with ids.
|
||||||
|
(Python only builds nested functions once, so there is no overhead for nesting)
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
|
||||||
|
db_model_name = item.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
db_model_name = GA(item.dbobj, "db_model_name")
|
||||||
|
return PackedDBobject(item.id, db_model_name, item.db_key)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple(iter_db2id(val) for val in item)
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return dict((key, iter_db2id(val)) for key, val in item.items())
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_db2id(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
dtype = type(data)
|
||||||
|
|
||||||
|
if dtype in (basestring, int, float):
|
||||||
|
return ("simple",data)
|
||||||
|
elif hasattr(data, "id") and hasattr(data, "db_model_name") and hasattr(data, 'db_key'):
|
||||||
|
# all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass)
|
||||||
|
# have the protected property db_model_name hardcoded on themselves for speed.
|
||||||
|
db_model_name = data.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
# typeclass cannot help us, we want the actual child object model name
|
||||||
|
db_model_name = GA(data.dbobj, "db_model_name")
|
||||||
|
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
|
||||||
|
elif hasattr(data, "__iter__"):
|
||||||
|
return ("iter", iter_db2id(data))
|
||||||
|
else:
|
||||||
|
return ("simple", data)
|
||||||
|
|
||||||
|
def from_attr(attr, datatuple):
|
||||||
|
"""
|
||||||
|
Retrieve data from a previously stored attribute. This
|
||||||
|
is always a dict with keys type and data.
|
||||||
|
|
||||||
|
datatuple comes from the database storage and has
|
||||||
|
the following format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string. is returned as-is.
|
||||||
|
dbobj - a single dbobj-id. This id is retrieved back from the database.
|
||||||
|
iter - an iterable. This is traversed iteratively, converting all found
|
||||||
|
dbobj-ids back to objects. Also, all lists and dictionaries are
|
||||||
|
returned as their PackedList/PackedDict counterparts in order to
|
||||||
|
allow in-place assignment such as obj.db.mylist[3] = val. Mylist
|
||||||
|
is then a PackedList that saves the data on the fly.
|
||||||
|
"""
|
||||||
|
# nested functions
|
||||||
|
def id2db(data):
|
||||||
|
"""
|
||||||
|
Convert db-stored dbref back to object
|
||||||
|
"""
|
||||||
|
mclass = CTYPEGET(model=data.db_model).model_class()
|
||||||
|
try:
|
||||||
|
return mclass.objects.dbref_search(data.id)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return mclass.objects.get(id=data.id)
|
||||||
|
except mclass.DoesNotExist: # could happen if object was deleted in the interim.
|
||||||
|
return None
|
||||||
|
|
||||||
|
def iter_id2db(item):
|
||||||
|
"""
|
||||||
|
Recursively looping through stored iterables, replacing ids with actual objects.
|
||||||
|
We return PackedDict and PackedLists instead of normal lists; this is needed in order for
|
||||||
|
the user to do dynamic saving of nested in-place, such as obj.db.attrlist[2]=3. What is
|
||||||
|
stored in the database are however always normal python primitives.
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif dtype == PackedDBobject:
|
||||||
|
return id2db(item)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple([iter_id2db(val) for val in item])
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return dict(zip([key for key in item.keys()],
|
||||||
|
[iter_id2db(val) for val in item.values()]))
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_id2db(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
typ, data = datatuple
|
||||||
|
|
||||||
|
if typ == 'simple':
|
||||||
|
# single non-db objects
|
||||||
|
return data
|
||||||
|
elif typ == 'dbobj':
|
||||||
|
# a single stored dbobj
|
||||||
|
return id2db(data)
|
||||||
|
elif typ == 'iter':
|
||||||
|
# all types of iterables
|
||||||
|
return iter_id2db(data)
|
||||||
|
|
||||||
|
class Migration(DataMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
"Write your forwards methods here."
|
||||||
|
|
||||||
|
for attr in orm.ObjAttribute.objects.all():
|
||||||
|
# repack attr into new format, and reimport
|
||||||
|
try:
|
||||||
|
val = pickle.loads(to_str(attr.db_value))
|
||||||
|
attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
|
||||||
|
attr.save()
|
||||||
|
except TypeError, RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
"Write your backwards methods here."
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'auth.permission': {
|
||||||
|
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'objects.alias': {
|
||||||
|
'Meta': {'object_name': 'Alias'},
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'objects.objattribute': {
|
||||||
|
'Meta': {'object_name': 'ObjAttribute'},
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'objects.objectdb': {
|
||||||
|
'Meta': {'object_name': 'ObjectDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'objects.objectnick': {
|
||||||
|
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'},
|
||||||
|
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_real': ('django.db.models.fields.TextField', [], {}),
|
||||||
|
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'players.playerdb': {
|
||||||
|
'Meta': {'object_name': 'PlayerDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['objects']
|
||||||
343
src/players/migrations/0009_converting_attributes.py
Normal file
343
src/players/migrations/0009_converting_attributes.py
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import DataMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
from src.utils.utils import to_str, to_unicode
|
||||||
|
from src.typeclasses.models import PackedDBobject
|
||||||
|
from src.players.models import PlayerAttribute
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
CTYPEGET = ContentType.objects.get
|
||||||
|
GA = object.__getattribute__
|
||||||
|
SA = object.__setattr__
|
||||||
|
DA = object.__delattr__
|
||||||
|
|
||||||
|
class PackedDict(dict):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of dict that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing dict. The db_store variable
|
||||||
|
is set by Attribute.validate_data() when returned in
|
||||||
|
order to allow custom updates to the dict.
|
||||||
|
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedDict, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items())
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"assign item to this dict"
|
||||||
|
super(PackedDict, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def clear(self, *args, **kwargs):
|
||||||
|
"Custom clear"
|
||||||
|
super(PackedDict, self).clear(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedDict, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def popitem(self, *args, **kwargs):
|
||||||
|
"Custom popitem"
|
||||||
|
super(PackedDict, self).popitem(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def update(self, *args, **kwargs):
|
||||||
|
"Custom update"
|
||||||
|
super(PackedDict, self).update(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
class PackedList(list):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of list that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing list.
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedList, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "[%s]" % ", ".join(str(val) for val in self)
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"Custom setitem that stores changed list to database."
|
||||||
|
super(PackedList, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def append(self, *args, **kwargs):
|
||||||
|
"Custom append"
|
||||||
|
super(PackedList, self).append(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def extend(self, *args, **kwargs):
|
||||||
|
"Custom extend"
|
||||||
|
super(PackedList, self).extend(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def insert(self, *args, **kwargs):
|
||||||
|
"Custom insert"
|
||||||
|
super(PackedList, self).insert(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def remove(self, *args, **kwargs):
|
||||||
|
"Custom remove"
|
||||||
|
super(PackedList, self).remove(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedList, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def reverse(self, *args, **kwargs):
|
||||||
|
"Custom reverse"
|
||||||
|
super(PackedList, self).reverse(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def sort(self, *args, **kwargs):
|
||||||
|
"Custom sort"
|
||||||
|
super(PackedList, self).sort(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
|
||||||
|
def to_attr(data):
|
||||||
|
"""
|
||||||
|
Convert data to proper attr data format before saving
|
||||||
|
|
||||||
|
We have to make sure to not store database objects raw, since
|
||||||
|
this will crash the system. Instead we must store their IDs
|
||||||
|
and make sure to convert back when the attribute is read back
|
||||||
|
later.
|
||||||
|
|
||||||
|
Due to this it's criticial that we check all iterables
|
||||||
|
recursively, converting all found database objects to a form
|
||||||
|
the database can handle. We handle lists, tuples and dicts
|
||||||
|
(and any nested combination of them) this way, all other
|
||||||
|
iterables are stored and returned as lists.
|
||||||
|
|
||||||
|
data storage format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string or number
|
||||||
|
dbobj - a single dbobj
|
||||||
|
iter - any iterable object - will be looped over recursively
|
||||||
|
to convert dbobj->id.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def iter_db2id(item):
|
||||||
|
"""
|
||||||
|
recursively looping through stored iterables, replacing objects with ids.
|
||||||
|
(Python only builds nested functions once, so there is no overhead for nesting)
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
|
||||||
|
db_model_name = item.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
db_model_name = GA(item.dbobj, "db_model_name")
|
||||||
|
return PackedDBobject(item.id, db_model_name, item.db_key)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple(iter_db2id(val) for val in item)
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return dict((key, iter_db2id(val)) for key, val in item.items())
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_db2id(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
dtype = type(data)
|
||||||
|
|
||||||
|
if dtype in (basestring, int, float):
|
||||||
|
return ("simple",data)
|
||||||
|
elif hasattr(data, "id") and hasattr(data, "db_model_name") and hasattr(data, 'db_key'):
|
||||||
|
# all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass)
|
||||||
|
# have the protected property db_model_name hardcoded on themselves for speed.
|
||||||
|
db_model_name = data.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
# typeclass cannot help us, we want the actual child object model name
|
||||||
|
db_model_name = GA(data.dbobj, "db_model_name")
|
||||||
|
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
|
||||||
|
elif hasattr(data, "__iter__"):
|
||||||
|
return ("iter", iter_db2id(data))
|
||||||
|
else:
|
||||||
|
return ("simple", data)
|
||||||
|
|
||||||
|
def from_attr(attr, datatuple):
|
||||||
|
"""
|
||||||
|
Retrieve data from a previously stored attribute. This
|
||||||
|
is always a dict with keys type and data.
|
||||||
|
|
||||||
|
datatuple comes from the database storage and has
|
||||||
|
the following format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string. is returned as-is.
|
||||||
|
dbobj - a single dbobj-id. This id is retrieved back from the database.
|
||||||
|
iter - an iterable. This is traversed iteratively, converting all found
|
||||||
|
dbobj-ids back to objects. Also, all lists and dictionaries are
|
||||||
|
returned as their PackedList/PackedDict counterparts in order to
|
||||||
|
allow in-place assignment such as obj.db.mylist[3] = val. Mylist
|
||||||
|
is then a PackedList that saves the data on the fly.
|
||||||
|
"""
|
||||||
|
# nested functions
|
||||||
|
def id2db(data):
|
||||||
|
"""
|
||||||
|
Convert db-stored dbref back to object
|
||||||
|
"""
|
||||||
|
mclass = CTYPEGET(model=data.db_model).model_class()
|
||||||
|
try:
|
||||||
|
return mclass.objects.dbref_search(data.id)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return mclass.objects.get(id=data.id)
|
||||||
|
except mclass.DoesNotExist: # could happen if object was deleted in the interim.
|
||||||
|
return None
|
||||||
|
|
||||||
|
def iter_id2db(item):
|
||||||
|
"""
|
||||||
|
Recursively looping through stored iterables, replacing ids with actual objects.
|
||||||
|
We return PackedDict and PackedLists instead of normal lists; this is needed in order for
|
||||||
|
the user to do dynamic saving of nested in-place, such as obj.db.attrlist[2]=3. What is
|
||||||
|
stored in the database are however always normal python primitives.
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif dtype == PackedDBobject:
|
||||||
|
return id2db(item)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple([iter_id2db(val) for val in item])
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return dict(zip([key for key in item.keys()],
|
||||||
|
[iter_id2db(val) for val in item.values()]))
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_id2db(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
typ, data = datatuple
|
||||||
|
|
||||||
|
if typ == 'simple':
|
||||||
|
# single non-db objects
|
||||||
|
return data
|
||||||
|
elif typ == 'dbobj':
|
||||||
|
# a single stored dbobj
|
||||||
|
return id2db(data)
|
||||||
|
elif typ == 'iter':
|
||||||
|
# all types of iterables
|
||||||
|
return iter_id2db(data)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(DataMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
"Write your forwards methods here."
|
||||||
|
for attr in orm.PlayerAttribute.objects.all():
|
||||||
|
try:
|
||||||
|
# repack attr into new format, and reimport
|
||||||
|
val = pickle.loads(to_str(attr.db_value))
|
||||||
|
attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
|
||||||
|
attr.save()
|
||||||
|
except TypeError, RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
"Write your backwards methods here."
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'auth.permission': {
|
||||||
|
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'objects.objectdb': {
|
||||||
|
'Meta': {'object_name': 'ObjectDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'players.playerattribute': {
|
||||||
|
'Meta': {'object_name': 'PlayerAttribute'},
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
|
||||||
|
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'players.playerdb': {
|
||||||
|
'Meta': {'object_name': 'PlayerDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||||
|
},
|
||||||
|
'players.playernick': {
|
||||||
|
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
|
||||||
|
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
|
||||||
|
'db_real': ('django.db.models.fields.TextField', [], {}),
|
||||||
|
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['players']
|
||||||
348
src/scripts/migrations/0006_converting_attributes.py
Normal file
348
src/scripts/migrations/0006_converting_attributes.py
Normal file
|
|
@ -0,0 +1,348 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import DataMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
from src.utils.utils import to_str, to_unicode
|
||||||
|
from src.typeclasses.models import PackedDBobject
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
CTYPEGET = ContentType.objects.get
|
||||||
|
GA = object.__getattribute__
|
||||||
|
SA = object.__setattr__
|
||||||
|
DA = object.__delattr__
|
||||||
|
|
||||||
|
class PackedDict(dict):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of dict that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing dict. The db_store variable
|
||||||
|
is set by Attribute.validate_data() when returned in
|
||||||
|
order to allow custom updates to the dict.
|
||||||
|
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedDict, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items())
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"assign item to this dict"
|
||||||
|
super(PackedDict, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def clear(self, *args, **kwargs):
|
||||||
|
"Custom clear"
|
||||||
|
super(PackedDict, self).clear(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedDict, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def popitem(self, *args, **kwargs):
|
||||||
|
"Custom popitem"
|
||||||
|
super(PackedDict, self).popitem(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def update(self, *args, **kwargs):
|
||||||
|
"Custom update"
|
||||||
|
super(PackedDict, self).update(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
class PackedList(list):
|
||||||
|
"""
|
||||||
|
Attribute helper class.
|
||||||
|
A variant of list that stores itself to the database when
|
||||||
|
updating one of its keys. This is called and handled by
|
||||||
|
Attribute.validate_data().
|
||||||
|
"""
|
||||||
|
def __init__(self, db_obj, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Sets up the packing list.
|
||||||
|
db_obj - the Attribute object storing this dict.
|
||||||
|
"""
|
||||||
|
self.db_obj = db_obj
|
||||||
|
super(PackedList, self).__init__(*args, **kwargs)
|
||||||
|
def __str__(self):
|
||||||
|
return "[%s]" % ", ".join(str(val) for val in self)
|
||||||
|
def __setitem__(self, *args, **kwargs):
|
||||||
|
"Custom setitem that stores changed list to database."
|
||||||
|
super(PackedList, self).__setitem__(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def append(self, *args, **kwargs):
|
||||||
|
"Custom append"
|
||||||
|
super(PackedList, self).append(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def extend(self, *args, **kwargs):
|
||||||
|
"Custom extend"
|
||||||
|
super(PackedList, self).extend(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def insert(self, *args, **kwargs):
|
||||||
|
"Custom insert"
|
||||||
|
super(PackedList, self).insert(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def remove(self, *args, **kwargs):
|
||||||
|
"Custom remove"
|
||||||
|
super(PackedList, self).remove(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def pop(self, *args, **kwargs):
|
||||||
|
"Custom pop"
|
||||||
|
super(PackedList, self).pop(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def reverse(self, *args, **kwargs):
|
||||||
|
"Custom reverse"
|
||||||
|
super(PackedList, self).reverse(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
def sort(self, *args, **kwargs):
|
||||||
|
"Custom sort"
|
||||||
|
super(PackedList, self).sort(*args, **kwargs)
|
||||||
|
self.db_obj.value = self
|
||||||
|
|
||||||
|
|
||||||
|
def to_attr(data):
|
||||||
|
"""
|
||||||
|
Convert data to proper attr data format before saving
|
||||||
|
|
||||||
|
We have to make sure to not store database objects raw, since
|
||||||
|
this will crash the system. Instead we must store their IDs
|
||||||
|
and make sure to convert back when the attribute is read back
|
||||||
|
later.
|
||||||
|
|
||||||
|
Due to this it's criticial that we check all iterables
|
||||||
|
recursively, converting all found database objects to a form
|
||||||
|
the database can handle. We handle lists, tuples and dicts
|
||||||
|
(and any nested combination of them) this way, all other
|
||||||
|
iterables are stored and returned as lists.
|
||||||
|
|
||||||
|
data storage format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string or number
|
||||||
|
dbobj - a single dbobj
|
||||||
|
iter - any iterable object - will be looped over recursively
|
||||||
|
to convert dbobj->id.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def iter_db2id(item):
|
||||||
|
"""
|
||||||
|
recursively looping through stored iterables, replacing objects with ids.
|
||||||
|
(Python only builds nested functions once, so there is no overhead for nesting)
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
|
||||||
|
db_model_name = item.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
db_model_name = GA(item.dbobj, "db_model_name")
|
||||||
|
return PackedDBobject(item.id, db_model_name, item.db_key)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple(iter_db2id(val) for val in item)
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return dict((key, iter_db2id(val)) for key, val in item.items())
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_db2id(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
dtype = type(data)
|
||||||
|
|
||||||
|
if dtype in (basestring, int, float):
|
||||||
|
return ("simple",data)
|
||||||
|
elif hasattr(data, "id") and hasattr(data, "db_model_name") and hasattr(data, 'db_key'):
|
||||||
|
# all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass)
|
||||||
|
# have the protected property db_model_name hardcoded on themselves for speed.
|
||||||
|
db_model_name = data.db_model_name
|
||||||
|
if db_model_name == "typeclass":
|
||||||
|
# typeclass cannot help us, we want the actual child object model name
|
||||||
|
db_model_name = GA(data.dbobj, "db_model_name")
|
||||||
|
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
|
||||||
|
elif hasattr(data, "__iter__"):
|
||||||
|
return ("iter", iter_db2id(data))
|
||||||
|
else:
|
||||||
|
return ("simple", data)
|
||||||
|
|
||||||
|
def from_attr(attr, datatuple):
|
||||||
|
"""
|
||||||
|
Retrieve data from a previously stored attribute. This
|
||||||
|
is always a dict with keys type and data.
|
||||||
|
|
||||||
|
datatuple comes from the database storage and has
|
||||||
|
the following format:
|
||||||
|
(simple|dbobj|iter, <data>)
|
||||||
|
where
|
||||||
|
simple - a single non-db object, like a string. is returned as-is.
|
||||||
|
dbobj - a single dbobj-id. This id is retrieved back from the database.
|
||||||
|
iter - an iterable. This is traversed iteratively, converting all found
|
||||||
|
dbobj-ids back to objects. Also, all lists and dictionaries are
|
||||||
|
returned as their PackedList/PackedDict counterparts in order to
|
||||||
|
allow in-place assignment such as obj.db.mylist[3] = val. Mylist
|
||||||
|
is then a PackedList that saves the data on the fly.
|
||||||
|
"""
|
||||||
|
# nested functions
|
||||||
|
def id2db(data):
|
||||||
|
"""
|
||||||
|
Convert db-stored dbref back to object
|
||||||
|
"""
|
||||||
|
mclass = CTYPEGET(model=data.db_model).model_class()
|
||||||
|
try:
|
||||||
|
return mclass.objects.dbref_search(data.id)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return mclass.objects.get(id=data.id)
|
||||||
|
except mclass.DoesNotExist: # could happen if object was deleted in the interim.
|
||||||
|
return None
|
||||||
|
|
||||||
|
def iter_id2db(item):
|
||||||
|
"""
|
||||||
|
Recursively looping through stored iterables, replacing ids with actual objects.
|
||||||
|
We return PackedDict and PackedLists instead of normal lists; this is needed in order for
|
||||||
|
the user to do dynamic saving of nested in-place, such as obj.db.attrlist[2]=3. What is
|
||||||
|
stored in the database are however always normal python primitives.
|
||||||
|
"""
|
||||||
|
dtype = type(item)
|
||||||
|
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||||
|
return item
|
||||||
|
elif dtype == PackedDBobject:
|
||||||
|
return id2db(item)
|
||||||
|
elif dtype == tuple:
|
||||||
|
return tuple([iter_id2db(val) for val in item])
|
||||||
|
elif dtype in (dict, PackedDict):
|
||||||
|
return attr, dict(zip([key for key in item.keys()],
|
||||||
|
[iter_id2db(val) for val in item.values()]))
|
||||||
|
elif hasattr(item, '__iter__'):
|
||||||
|
return list(iter_id2db(val) for val in item)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
typ, data = datatuple
|
||||||
|
|
||||||
|
if typ == 'simple':
|
||||||
|
# single non-db objects
|
||||||
|
return data
|
||||||
|
elif typ == 'dbobj':
|
||||||
|
# a single stored dbobj
|
||||||
|
return id2db(data)
|
||||||
|
elif typ == 'iter':
|
||||||
|
# all types of iterables
|
||||||
|
return iter_id2db(data)
|
||||||
|
|
||||||
|
class Migration(DataMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
"Write your forwards methods here."
|
||||||
|
for attr in orm.ScriptAttribute.objects.all():
|
||||||
|
try:
|
||||||
|
# repack attr into new format, and reimport
|
||||||
|
val = pickle.loads(to_str(attr.db_value))
|
||||||
|
attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
|
||||||
|
attr.save()
|
||||||
|
except TypeError, RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
"Write your backwards methods here."
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'auth.permission': {
|
||||||
|
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'objects.objectdb': {
|
||||||
|
'Meta': {'object_name': 'ObjectDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'players.playerdb': {
|
||||||
|
'Meta': {'object_name': 'PlayerDB'},
|
||||||
|
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||||
|
},
|
||||||
|
'scripts.scriptattribute': {
|
||||||
|
'Meta': {'object_name': 'ScriptAttribute'},
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['scripts.ScriptDB']"}),
|
||||||
|
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'scripts.scriptdb': {
|
||||||
|
'Meta': {'object_name': 'ScriptDB'},
|
||||||
|
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||||
|
'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||||
|
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||||
|
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||||
|
'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['scripts']
|
||||||
Loading…
Add table
Add a link
Reference in a new issue