Committin a 'working' checkpoint before I break more stuff.

This commit is contained in:
Greg Taylor 2008-06-15 19:06:31 +00:00
parent ccf078b5c8
commit d3808c1ea2
18 changed files with 494 additions and 444 deletions

View file

@ -0,0 +1,11 @@
"""
Exceptions for the object application.
"""
from src.exceptions_generic import GenericException
class ObjectNotExist(GenericException):
"""
Raised when an object is queried for but does not exist.
"""
def __str__(self):
return repr("No such object: %s" % self.value)

View file

@ -0,0 +1,18 @@
"""
Custom manager for Attribute objects.
"""
from django.db import models
import defines_global
class AttributeManager(models.Manager):
def is_modifiable_attrib(self, attribname):
"""
Check to see if a particular attribute is modifiable.
attribname: (string) An attribute name to check.
"""
if attribname.upper() not in defines_global.NOSET_ATTRIBS:
return True
else:
return False

View file

@ -1,8 +1,348 @@
""" """
Custom manager for Object objects. Custom manager for Object objects.
""" """
import sets
from datetime import datetime, timedelta
from django.db import models from django.db import models
from django.db import connection
from django.contrib.auth.models import User
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from apps.config.models import ConfigValue
from apps.objects.exceptions import ObjectNotExist
from apps.objects.util import object as util_object
import defines_global
class ObjectManager(models.Manager): class ObjectManager(models.Manager):
pass def num_total_players(self):
"""
Returns the total number of registered players.
"""
return User.objects.count()
def get_connected_players(self):
"""
Returns the a QuerySet containing the currently connected players.
"""
return self.filter(nosave_flags__contains="CONNECTED")
def get_recently_created_users(self, days=7):
"""
Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days.
"""
end_date = datetime.now()
tdelta = timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(date_joined__range=(start_date, end_date))
def get_recently_connected_users(self, days=7):
"""
Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days.
"""
end_date = datetime.now()
tdelta = timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(last_login__range=(start_date, end_date)).order_by('-last_login')
def get_nextfree_dbnum(self):
"""
Figure out what our next free database reference number is.
If we need to recycle a GARBAGE object, return the object to recycle
Otherwise, return the first free dbref.
"""
# First we'll see if there's an object of type 6 (GARBAGE) that we
# can recycle.
nextfree = self.filter(type__exact=defines_global.OTYPE_GARBAGE)
if nextfree:
# We've got at least one garbage object to recycle.
return nextfree.id
else:
# No garbage to recycle, find the highest dbnum and increment it
# for our next free.
return int(self.order_by('-id')[0].id + 1)
def global_object_name_search(self, ostring, exact_match=False):
"""
Searches through all objects for a name match.
"""
if exact_match:
o_query = self.filter(name__iexact=ostring)
else:
o_query = self.filter(name__icontains=ostring)
return o_query.exclude(type=defines_global.OTYPE_GARBAGE)
def list_search_object_namestr(self, searchlist, ostring, dbref_only=False, limit_types=False, match_type="fuzzy"):
"""
Iterates through a list of objects and returns a list of
name matches.
searchlist: (List of Objects) The objects to perform name comparisons on.
ostring: (string) The string to match against.
dbref_only: (bool) Only compare dbrefs.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
if dbref_only:
if limit_types:
return [prospect for prospect in searchlist if prospect.dbref_match(ostring) and prospect.type in limit_types]
else:
return [prospect for prospect in searchlist if prospect.dbref_match(ostring)]
else:
if limit_types:
return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type) and prospect.type in limit_types]
else:
return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)]
def standard_plr_objsearch(self, session, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
"""
Perform a standard object search via a player session, handling multiple
results and lack thereof gracefully.
session: (SessionProtocol) Reference to the player's session.
ostring: (str) The string to match object names against.
"""
pobject = session.get_pobject()
results = self.local_and_global_search(pobject, ostring, search_contents=search_contents, search_location=search_location, dbref_only=dbref_only, limit_types=limit_types)
if len(results) > 1:
session.msg("More than one match found (please narrow target):")
for result in results:
session.msg(" %s" % (result.get_name(),))
return False
elif len(results) == 0:
session.msg("I don't see that here.")
return False
else:
return results[0]
def object_totals(self):
"""
Returns a dictionary with database object totals.
"""
dbtotals = {
"objects": self.count(),
"things": self.filter(type=defines_global.OTYPE_THING).count(),
"exits": self.filter(type=defines_global.OTYPE_EXIT).count(),
"rooms": self.filter(type=defines_global.OTYPE_ROOM).count(),
"garbage": self.filter(type=defines_global.OTYPE_GARBAGE).count(),
"players": self.filter(type=defines_global.OTYPE_PLAYER).count(),
}
return dbtotals
def player_alias_search(self, searcher, ostring):
"""
Search players by alias. Returns a list of objects whose "ALIAS" attribute
exactly (not case-sensitive) matches ostring.
searcher: (Object) The object doing the searching.
ostring: (string) The alias string to search for.
"""
search_query = ''.join(ostring)
Attribute = ContentType.objects.get(app_label="objects", model="attribute").get_model()
results = Attribute.objects.select_related().filter(attr_name__exact="ALIAS").filter(attr_value__iexact=ostring)
return [prospect.get_object() for prospect in results if prospect.get_object().is_player()]
def player_name_search(self, search_string):
"""
Combines an alias and global search for a player's name. If there are
no alias matches, do a global search limiting by type PLAYER.
search_string: (string) The name string to search for.
"""
# Handle the case where someone might have started the search_string
# with a *
if search_string.startswith('*') is True:
search_string = search_string[1:]
# Use Q objects to build complex OR query to look at either
# the player name or ALIAS attribute
player_filter = Q(name__iexact=search_string)
alias_filter = Q(attribute__attr_name__exact="ALIAS") & \
Q(attribute__attr_value__iexact=search_string)
player_matches = self.filter(
player_filter | alias_filter).filter(
type=defines_global.OTYPE_PLAYER).distinct()
try:
return player_matches[0]
except IndexError:
return None
def dbref_search(self, dbref_string, limit_types=False):
"""
Searches for a given dbref.
dbref_number: (string) The dbref to search for
limit_types: (list of int) A list of Object type numbers to filter by.
"""
if not util_object.is_dbref(dbref_string):
return None
dbref_string = dbref_string[1:]
dbref_matches = self.filter(id=dbref_string).exclude(
type=defines_global.OTYPE_GARBAGE)
# Check for limiters
if limit_types is not False:
for limiter in limit_types:
dbref_matches.filter(type=limiter)
try:
return dbref_matches[0]
except IndexError:
return None
def local_and_global_search(self, searcher, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
"""
Searches an object's location then globally for a dbref or name match.
searcher: (Object) The object performing the search.
ostring: (string) The string to compare names against.
search_contents: (bool) While true, check the contents of the searcher.
search_location: (bool) While true, check the searcher's surroundings.
dbref_only: (bool) Only compare dbrefs.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
search_query = ''.join(ostring)
# This is a global dbref search. Not applicable if we're only searching
# searcher's contents/locations, dbref comparisons for location/contents
# searches are handled by list_search_object_namestr() below.
if util_object.is_dbref(ostring):
search_num = search_query[1:]
dbref_match = dbref_search(search_num, limit_types)
if dbref_match is not None:
return [dbref_match]
# If the search string is one of the following, return immediately with
# the appropriate result.
if searcher.get_location().dbref_match(ostring) or ostring == 'here':
return [searcher.get_location()]
elif ostring == 'me' and searcher:
return [searcher]
if search_query[0] == "*":
# Player search- gotta search by name or alias
search_target = search_query[1:]
player_match = player_name_search(search_target)
if player_match is not None:
return [player_match]
local_matches = []
# Handle our location/contents searches. list_search_object_namestr() does
# name and dbref comparisons against search_query.
if search_contents:
local_matches += list_search_object_namestr(searcher.get_contents(), search_query, limit_types)
if search_location:
local_matches += list_search_object_namestr(searcher.get_location().get_contents(), search_query, limit_types=limit_types)
return local_matches
def get_user_from_email(self, uemail):
"""
Returns a player's User object when given an email address.
"""
return User.objects.filter(email__iexact=uemail)
def get_object_from_dbref(self, dbref):
"""
Returns an object when given a dbref.
"""
try:
return self.get(id=dbref)
except self.model.DoesNotExist:
raise ObjectNotExist(dbref)
def create_object(self, odat):
"""
Create a new object. odat is a dictionary that contains the following keys.
REQUIRED KEYS:
* type: Integer representing the object's type.
* name: The name of the new object.
* location: Reference to another object for the new object to reside in.
* owner: The creator of the object.
OPTIONAL KEYS:
* home: Reference to another object to home to. If not specified, use
location key for home.
"""
next_dbref = get_nextfree_dbnum()
new_object = Object()
new_object.id = next_dbref
new_object.type = odat["type"]
new_object.set_name(odat["name"])
# If this is a player, we don't want him owned by anyone.
# The get_owner() function will return that the player owns
# himself.
if odat["type"] == 1:
new_object.owner = None
new_object.zone = None
else:
new_object.owner = odat["owner"]
if new_object.get_owner().get_zone():
new_object.zone = new_object.get_owner().get_zone()
# If we have a 'home' key, use that for our home value. Otherwise use
# the location key.
if odat.has_key("home"):
new_object.home = odat["home"]
else:
if new_object.is_exit():
new_object.home = None
else:
new_object.home = odat["location"]
new_object.save()
# Rooms have a NULL location.
if not new_object.is_room():
new_object.move_to(odat['location'])
return new_object
def create_user(self, cdat, uname, email, password):
"""
Handles the creation of new users.
"""
session = cdat['session']
server = cdat['server']
start_room = int(ConfigValue.objects.get_configvalue('player_dbnum_start'))
start_room_obj = get_object_from_dbref(start_room)
# The user's entry in the User table must match up to an object
# on the object table. The id's are the same, we need to figure out
# the next free unique ID to use and make sure the two entries are
# the same number.
uid = get_nextfree_dbnum()
print 'UID', uid
# If this is an object, we know to recycle it since it's garbage. We'll
# pluck the user ID from it.
if not str(uid).isdigit():
uid = uid.id
print 'UID2', uid
user = User.objects.create_user(uname, email, password)
# It stinks to have to do this but it's the only trivial way now.
user.save()
# We can't use the user model to change the id because of the way keys
# are handled, so we actually need to fall back to raw SQL. Boo hiss.
cursor = connection.cursor()
cursor.execute("UPDATE auth_user SET id=%d WHERE id=%d" % (uid, user.id))
# Grab the user object again since we've changed it and the old reference
# is no longer valid.
user = User.objects.get(id=uid)
# Create a player object of the same ID in the Objects table.
odat = {"id": uid, "name": uname, "type": 1, "location": start_room_obj, "owner": None}
user_object = create_object(odat)
# Activate the player's session and set them loose.
session.login(user)
print 'Registration: %s' % (session,)
session.msg("Welcome to %s, %s.\n\r" % (
ConfigValue.objects.get_configvalue('site_name'),
session.get_pobject().get_name(show_dbref=False)))

View file

@ -6,9 +6,12 @@ from django.contrib.auth.models import User, Group
import scripthandler import scripthandler
import defines_global import defines_global
import ansi import ansi
import src.flags
from apps.config.models import ConfigValue from apps.config.models import ConfigValue
from apps.objects.util import object as util_object
from apps.objects.managers.commchannel import CommChannelManager from apps.objects.managers.commchannel import CommChannelManager
from apps.objects.managers.object import ObjectManager from apps.objects.managers.object import ObjectManager
from apps.objects.managers.attribute import AttributeManager
class Attribute(models.Model): class Attribute(models.Model):
""" """
@ -24,6 +27,8 @@ class Attribute(models.Model):
attr_hidden = models.BooleanField(default=0) attr_hidden = models.BooleanField(default=0)
attr_object = models.ForeignKey("Object") attr_object = models.ForeignKey("Object")
objects = AttributeManager()
def __str__(self): def __str__(self):
return "%s(%s)" % (self.attr_name, self.id) return "%s(%s)" % (self.attr_name, self.id)
@ -550,7 +555,7 @@ class Object(models.Model):
if value == False and has_flag: if value == False and has_flag:
# Clear the flag. # Clear the flag.
if functions_db.is_unsavable_flag(flag): if src.flags.is_unsavable_flag(flag):
# Not a savable flag (CONNECTED, etc) # Not a savable flag (CONNECTED, etc)
flags = self.nosave_flags.split() flags = self.nosave_flags.split()
flags.remove(flag) flags.remove(flag)
@ -570,7 +575,7 @@ class Object(models.Model):
pass pass
else: else:
# Setting a flag. # Setting a flag.
if functions_db.is_unsavable_flag(flag): if src.flags.is_unsavable_flag(flag):
# Not a savable flag (CONNECTED, etc) # Not a savable flag (CONNECTED, etc)
flags = str(self.nosave_flags).split() flags = str(self.nosave_flags).split()
flags.append(flag) flags.append(flag)
@ -707,7 +712,7 @@ class Object(models.Model):
oname: (str) Name to match against. oname: (str) Name to match against.
""" """
if not functions_db.is_dbref(oname): if not util_object.is_dbref(oname):
return False return False
try: try:
@ -888,6 +893,5 @@ class CommChannelMessage(models.Model):
class Admin: class Admin:
list_display = ('channel', 'message') list_display = ('channel', 'message')
import functions_db
import functions_general import functions_general
import session_mgr import session_mgr

View file

View file

@ -0,0 +1,19 @@
"""
Utility functions for the Object class. These functions should not import
any models or modify the database.
"""
def is_dbref(dbstring):
"""
Is the input a well-formed dbref number?
"""
try:
number = int(dbstring[1:])
except ValueError:
return False
if not dbstring.startswith("#"):
return False
elif number < 1:
return False
else:
return True

View file

@ -6,9 +6,9 @@ something.
from traceback import format_exc from traceback import format_exc
import time import time
from apps.objects.models import Object
import defines_global import defines_global
import cmdtable import cmdtable
import functions_db
import functions_general import functions_general
import functions_log import functions_log
import functions_comsys import functions_comsys
@ -23,7 +23,7 @@ def match_exits(pobject, searchstr):
See if we can find an input match to exits. See if we can find an input match to exits.
""" """
exits = pobject.get_location().get_contents(filter_type=4) exits = pobject.get_location().get_contents(filter_type=4)
return functions_db.list_search_object_namestr(exits, searchstr, match_type="exact") return Object.objects.list_search_object_namestr(exits, searchstr, match_type="exact")
def parse_command(command_string): def parse_command(command_string):
""" """

View file

@ -1,16 +1,15 @@
"""
Comsys command module. Pretty much every comsys command should go here for
now.
"""
import time import time
from django.conf import settings from django.conf import settings
import functions_general import functions_general
import functions_db
import functions_comsys import functions_comsys
import defines_global import defines_global
import ansi import ansi
"""
Comsys command module. Pretty much every comsys command should go here for
now.
"""
def cmd_addcom(cdat): def cmd_addcom(cdat):
""" """

View file

@ -8,8 +8,8 @@ from django.conf import settings
from apps.config.models import ConfigValue from apps.config.models import ConfigValue
from apps.helpsys.models import HelpEntry from apps.helpsys.models import HelpEntry
from apps.objects.models import Object
import functions_general import functions_general
import functions_db
import defines_global import defines_global
import session_mgr import session_mgr
import ansi import ansi
@ -110,7 +110,7 @@ def cmd_look(cdat):
if len(args) == 0: if len(args) == 0:
target_obj = pobject.get_location() target_obj = pobject.get_location()
else: else:
target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -139,7 +139,7 @@ def cmd_get(cdat):
session.msg("Get what?") session.msg("Get what?")
return return
else: else:
target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_contents=False) target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args), search_contents=False)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -178,7 +178,7 @@ def cmd_drop(cdat):
session.msg("Drop what?") session.msg("Drop what?")
return return
else: else:
target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_location=False) target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args), search_location=False)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -224,7 +224,7 @@ def cmd_examine(cdat):
else: else:
searchstr = ' '.join(args) searchstr = ' '.join(args)
target_obj = functions_db.standard_plr_objsearch(session, searchstr) target_obj = Object.objects.standard_plr_objsearch(session, searchstr)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -302,9 +302,9 @@ def cmd_page(cdat):
last_paged_dbref_list = [ last_paged_dbref_list = [
x.strip() for x in last_paged_dbrefs.split(',')] x.strip() for x in last_paged_dbrefs.split(',')]
for dbref in last_paged_dbref_list: for dbref in last_paged_dbref_list:
if not functions_db.is_dbref(dbref): if not Object.objects.is_dbref(dbref):
raise ValueError raise ValueError
last_paged_object = functions_db.dbref_search(dbref) last_paged_object = Object.objects.dbref_search(dbref)
if last_paged_object is not None: if last_paged_object is not None:
last_paged_objects.append(last_paged_object) last_paged_objects.append(last_paged_object)
except ValueError: except ValueError:
@ -332,7 +332,7 @@ def cmd_page(cdat):
targets = dict([(target, 1) for target in last_paged_objects]) targets = dict([(target, 1) for target in last_paged_objects])
else: else:
# First try to match the entire target string against a single player # First try to match the entire target string against a single player
full_target_match = functions_db.player_name_search( full_target_match = Object.objects.player_name_search(
parsed_command['original_targets']) parsed_command['original_targets'])
if full_target_match is not None: if full_target_match is not None:
targets[full_target_match] = 1 targets[full_target_match] = 1
@ -341,9 +341,9 @@ def cmd_page(cdat):
# it to the targets list # it to the targets list
for target in parsed_command['targets']: for target in parsed_command['targets']:
# If the target is a dbref, behave appropriately # If the target is a dbref, behave appropriately
if functions_db.is_dbref(target): if Object.objects.is_dbref(target):
session.msg("Is dbref.") session.msg("Is dbref.")
matched_object = functions_db.dbref_search(target, matched_object = Object.objects.dbref_search(target,
limit_types=[defines_global.OTYPE_PLAYER]) limit_types=[defines_global.OTYPE_PLAYER])
if matched_object is not None: if matched_object is not None:
targets[matched_object] = 1 targets[matched_object] = 1
@ -353,7 +353,7 @@ def cmd_page(cdat):
target)) target))
else: else:
# Not a dbref, so must be a username, treat it as such # Not a dbref, so must be a username, treat it as such
matched_object = functions_db.player_name_search( matched_object = Object.objects.player_name_search(
target) target)
if matched_object is not None: if matched_object is not None:
targets[matched_object] = 1 targets[matched_object] = 1

View file

@ -11,7 +11,7 @@ if not functions_general.host_os_is('nt'):
# Don't import the resource module if the host OS is Windows. # Don't import the resource module if the host OS is Windows.
import resource import resource
import functions_db from apps.objects.models import Object
import scheduler import scheduler
import defines_global import defines_global
@ -99,7 +99,7 @@ def cmd_stats(cdat):
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage) 4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
""" """
session = cdat['session'] session = cdat['session']
stats_dict = functions_db.object_totals() stats_dict = Object.objects.object_totals()
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"], session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"],
stats_dict["rooms"], stats_dict["rooms"],
stats_dict["exits"], stats_dict["exits"],

View file

@ -1,6 +1,10 @@
"""
These commands typically are to do with building or modifying Objects.
"""
from apps.objects.models import Object
import src.flags
import ansi import ansi
import session_mgr import session_mgr
import functions_db
def cmd_teleport(cdat): def cmd_teleport(cdat):
""" """
@ -23,12 +27,12 @@ def cmd_teleport(cdat):
# a direct teleport, @tel <destination>. # a direct teleport, @tel <destination>.
if len(eq_args) > 1: if len(eq_args) > 1:
# Equal sign teleport. # Equal sign teleport.
victim = functions_db.standard_plr_objsearch(session, eq_args[0]) victim = Object.objects.standard_plr_objsearch(session, eq_args[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not victim: if not victim:
return return
destination = functions_db.standard_plr_objsearch(session, eq_args[1]) destination = Object.objects.standard_plr_objsearch(session, eq_args[1])
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not destination: if not destination:
return return
@ -53,7 +57,7 @@ def cmd_teleport(cdat):
else: else:
# Direct teleport (no equal sign) # Direct teleport (no equal sign)
target_obj = functions_db.standard_plr_objsearch(session, search_str) target_obj = Object.objects.standard_plr_objsearch(session, search_str)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -71,7 +75,7 @@ def cmd_stats(cdat):
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage) 4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
""" """
session = cdat['session'] session = cdat['session']
stats_dict = functions_db.object_totals() stats_dict = Object.objects.object_totals()
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"], session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"],
stats_dict["rooms"], stats_dict["rooms"],
stats_dict["exits"], stats_dict["exits"],
@ -98,13 +102,13 @@ def cmd_alias(cdat):
session.msg("Alias missing.") session.msg("Alias missing.")
return return
target = functions_db.standard_plr_objsearch(session, eq_args[0]) target = Object.objects.standard_plr_objsearch(session, eq_args[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target: if not target:
session.msg("Alias whom?") session.msg("Alias whom?")
return return
duplicates = functions_db.alias_search(pobject, eq_args[1]) duplicates = Object.objects.player_alias_search(pobject, eq_args[1])
if duplicates: if duplicates:
session.msg("Alias '%s' already exists." % (eq_args[1],)) session.msg("Alias '%s' already exists." % (eq_args[1],))
@ -145,7 +149,7 @@ def cmd_wipe(cdat):
else: else:
searchstr = ' '.join(args) searchstr = ' '.join(args)
target_obj = functions_db.standard_plr_objsearch(session, searchstr) target_obj = Object.objects.standard_plr_objsearch(session, searchstr)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -189,7 +193,7 @@ def cmd_set(cdat):
session.msg("Set what?") session.msg("Set what?")
return return
victim = functions_db.standard_plr_objsearch(session, eq_args[0]) victim = Object.objects.standard_plr_objsearch(session, eq_args[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not victim: if not victim:
return return
@ -207,7 +211,7 @@ def cmd_set(cdat):
attrib_value = eq_args[1][splicenum:] attrib_value = eq_args[1][splicenum:]
# In global_defines.py, see NOSET_ATTRIBS for protected attribute names. # In global_defines.py, see NOSET_ATTRIBS for protected attribute names.
if not functions_db.is_modifiable_attrib(attrib_name) and not pobject.is_superuser(): if not src.flags.is_modifiable_attrib(attrib_name) and not pobject.is_superuser():
session.msg("You can't modify that attribute.") session.msg("You can't modify that attribute.")
return return
@ -229,14 +233,14 @@ def cmd_set(cdat):
if flag[0] == '!': if flag[0] == '!':
# We're un-setting the flag. # We're un-setting the flag.
flag = flag[1:] flag = flag[1:]
if not functions_db.is_modifiable_flag(flag): if not src.flags.is_modifiable_flag(flag):
session.msg("You can't set/unset the flag - %s." % (flag,)) session.msg("You can't set/unset the flag - %s." % (flag,))
else: else:
session.msg('%s - %s cleared.' % (victim.get_name(), flag.upper(),)) session.msg('%s - %s cleared.' % (victim.get_name(), flag.upper(),))
victim.set_flag(flag, False) victim.set_flag(flag, False)
else: else:
# We're setting the flag. # We're setting the flag.
if not functions_db.is_modifiable_flag(flag): if not src.flags.is_modifiable_flag(flag):
session.msg("You can't set/unset the flag - %s." % (flag,)) session.msg("You can't set/unset the flag - %s." % (flag,))
else: else:
session.msg('%s - %s set.' % (victim.get_name(), flag.upper(),)) session.msg('%s - %s set.' % (victim.get_name(), flag.upper(),))
@ -256,7 +260,7 @@ def cmd_find(cdat):
session.msg("No search pattern given.") session.msg("No search pattern given.")
return return
results = functions_db.global_object_name_search(searchstring) results = Object.objects.global_object_name_search(searchstring)
if len(results) > 0: if len(results) > 0:
session.msg("Name matches for: %s" % (searchstring,)) session.msg("Name matches for: %s" % (searchstring,))
@ -281,7 +285,7 @@ def cmd_create(cdat):
else: else:
# Create and set the object up. # Create and set the object up.
odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject}
new_object = functions_db.create_object(odat) new_object = Object.objects.create_object(odat)
session.msg("You create a new thing: %s" % (new_object,)) session.msg("You create a new thing: %s" % (new_object,))
@ -291,7 +295,7 @@ def cmd_nextfree(cdat):
""" """
session = cdat['session'] session = cdat['session']
nextfree = functions_db.get_nextfree_dbnum() nextfree = Object.objects.get_nextfree_dbnum()
session.msg("Next free object number: #%s" % (nextfree,)) session.msg("Next free object number: #%s" % (nextfree,))
def cmd_open(cdat): def cmd_open(cdat):
@ -325,7 +329,7 @@ def cmd_open(cdat):
if len(eq_args) > 1: if len(eq_args) > 1:
# Opening an exit to another location via @open <Name>=<Dbref>[,<Name>]. # Opening an exit to another location via @open <Name>=<Dbref>[,<Name>].
comma_split = eq_args[1].split(',') comma_split = eq_args[1].split(',')
destination = functions_db.standard_plr_objsearch(session, comma_split[0]) destination = Object.objects.standard_plr_objsearch(session, comma_split[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not destination: if not destination:
return return
@ -335,20 +339,20 @@ def cmd_open(cdat):
return return
odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":destination} odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":destination}
new_object = functions_db.create_object(odat) new_object = Object.objects.create_object(odat)
session.msg("You open the an exit - %s to %s" % (new_object.get_name(),destination.get_name())) session.msg("You open the an exit - %s to %s" % (new_object.get_name(),destination.get_name()))
if len(comma_split) > 1: if len(comma_split) > 1:
second_exit_name = ','.join(comma_split[1:]) second_exit_name = ','.join(comma_split[1:])
odat = {"name": second_exit_name, "type": 4, "location": destination, "owner": pobject, "home": pobject.get_location()} odat = {"name": second_exit_name, "type": 4, "location": destination, "owner": pobject, "home": pobject.get_location()}
new_object = functions_db.create_object(odat) new_object = Object.objects.create_object(odat)
session.msg("You open the an exit - %s to %s" % (new_object.get_name(),pobject.get_location().get_name())) session.msg("You open the an exit - %s to %s" % (new_object.get_name(),pobject.get_location().get_name()))
else: else:
# Create an un-linked exit. # Create an un-linked exit.
odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":None} odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":None}
new_object = functions_db.create_object(odat) new_object = Object.objects.create_object(odat)
session.msg("You open an unlinked exit - %s" % (new_object,)) session.msg("You open an unlinked exit - %s" % (new_object,))
@ -377,7 +381,7 @@ def cmd_link(cdat):
return return
if len(eq_args) > 1: if len(eq_args) > 1:
target_obj = functions_db.standard_plr_objsearch(session, target_name) target_obj = Object.objects.standard_plr_objsearch(session, target_name)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -392,7 +396,7 @@ def cmd_link(cdat):
session.msg("You have unlinked %s." % (target_obj,)) session.msg("You have unlinked %s." % (target_obj,))
return return
destination = functions_db.standard_plr_objsearch(session, dest_name) destination = Object.objects.standard_plr_objsearch(session, dest_name)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not destination: if not destination:
return return
@ -417,7 +421,7 @@ def cmd_unlink(cdat):
session.msg("Unlink what?") session.msg("Unlink what?")
return return
else: else:
target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -443,7 +447,7 @@ def cmd_dig(cdat):
else: else:
# Create and set the object up. # Create and set the object up.
odat = {"name": roomname, "type": 2, "location": None, "owner": pobject} odat = {"name": roomname, "type": 2, "location": None, "owner": pobject}
new_object = functions_db.create_object(odat) new_object = Object.objects.create_object(odat)
session.msg("You create a new room: %s" % (new_object,)) session.msg("You create a new room: %s" % (new_object,))
@ -462,7 +466,7 @@ def cmd_name(cdat):
elif len(eq_args) < 2: elif len(eq_args) < 2:
session.msg("What would you like to name that object?") session.msg("What would you like to name that object?")
else: else:
target_obj = functions_db.standard_plr_objsearch(session, searchstring) target_obj = Object.objects.standard_plr_objsearch(session, searchstring)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -489,7 +493,7 @@ def cmd_description(cdat):
elif len(eq_args) < 2: elif len(eq_args) < 2:
session.msg("How would you like to describe that object?") session.msg("How would you like to describe that object?")
else: else:
target_obj = functions_db.standard_plr_objsearch(session, searchstring) target_obj = Object.objects.standard_plr_objsearch(session, searchstring)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
@ -519,7 +523,7 @@ def cmd_destroy(cdat):
session.msg("Destroy what?") session.msg("Destroy what?")
return return
else: else:
target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return

View file

@ -1,6 +1,6 @@
from apps.objects.models import Object
import defines_global import defines_global
import functions_general import functions_general
import functions_db
import ansi import ansi
""" """
@ -52,7 +52,7 @@ def cmd_boot(cdat):
break break
else: else:
# Grab the objects that match # Grab the objects that match
objs = functions_db.global_object_name_search(searchstring) objs = Objects.object.global_object_name_search(searchstring)
if len(objs) < 1: if len(objs) < 1:
session.msg("Who would you like to boot?") session.msg("Who would you like to boot?")
@ -98,7 +98,7 @@ def cmd_newpassword(cdat):
session.msg("You must supply a new password.") session.msg("You must supply a new password.")
return return
target_obj = functions_db.standard_plr_objsearch(session, searchstring) target_obj = Objects.object.standard_plr_objsearch(session, searchstring)
# Use standard_plr_objsearch to handle duplicate/nonexistant results. # Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return

View file

@ -1,12 +1,11 @@
from django.contrib.auth.models import User
from apps.objects.models import Attribute, Object
import functions_db
import functions_general
import defines_global
""" """
Commands that are available from the connect screen. Commands that are available from the connect screen.
""" """
from django.contrib.auth.models import User
from apps.objects.models import Attribute, Object
import functions_general
import defines_global
def cmd_connect(cdat): def cmd_connect(cdat):
""" """
@ -24,7 +23,7 @@ def cmd_connect(cdat):
password = cdat['uinput']['splitted'][2] password = cdat['uinput']['splitted'][2]
# Match an email address to an account. # Match an email address to an account.
email_matches = functions_db.get_user_from_email(uemail) email_matches = Object.objects.get_user_from_email(uemail)
autherror = "Specified email does not match any accounts!" autherror = "Specified email does not match any accounts!"
# No username match # No username match
@ -71,7 +70,7 @@ def cmd_create(cdat):
# Search for a user object with the specified username. # Search for a user object with the specified username.
account = User.objects.filter(username=uname) account = User.objects.filter(username=uname)
# Match an email address to an account. # Match an email address to an account.
email_matches = functions_db.get_user_from_email(email) email_matches = Object.objects.get_user_from_email(email)
# Look for any objects with an 'Alias' attribute that matches # Look for any objects with an 'Alias' attribute that matches
# the requested username # the requested username
alias_matches = Object.objects.filter(attribute__attr_name__exact="ALIAS", alias_matches = Object.objects.filter(attribute__attr_name__exact="ALIAS",
@ -85,7 +84,7 @@ def cmd_create(cdat):
elif len(password) < 3: elif len(password) < 3:
session.msg("Your password must be 3 characters or longer.") session.msg("Your password must be 3 characters or longer.")
else: else:
functions_db.create_user(cdat, uname, email, password) Object.objects.create_user(cdat, uname, email, password)
def cmd_quit(cdat): def cmd_quit(cdat):
""" """

View file

@ -1,378 +0,0 @@
import sets
from datetime import datetime, timedelta
from django.db import connection
from django.contrib.auth.models import User
from django.db.models import Q
from apps.objects.models import Object, Attribute
from apps.config.models import ConfigValue
import defines_global
"""
Common database functions.
"""
def num_total_players():
"""
Returns the total number of registered players.
"""
return User.objects.count()
def get_connected_players():
"""
Returns the a QuerySet containing the currently connected players.
"""
return Object.objects.filter(nosave_flags__contains="CONNECTED")
def get_recently_created_players(days=7):
"""
Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days.
"""
end_date = datetime.now()
tdelta = timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(date_joined__range=(start_date, end_date))
def get_recently_connected_players(days=7):
"""
Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days.
"""
end_date = datetime.now()
tdelta = timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(last_login__range=(start_date, end_date)).order_by('-last_login')
def is_unsavable_flag(flagname):
"""
Returns TRUE if the flag is an unsavable flag.
"""
return flagname.upper() in defines_global.NOSAVE_FLAGS
def is_modifiable_flag(flagname):
"""
Check to see if a particular flag is modifiable.
"""
if flagname.upper() not in defines_global.NOSET_FLAGS:
return True
else:
return False
def is_modifiable_attrib(attribname):
"""
Check to see if a particular attribute is modifiable.
attribname: (string) An attribute name to check.
"""
if attribname.upper() not in defines_global.NOSET_ATTRIBS:
return True
else:
return False
def get_nextfree_dbnum():
"""
Figure out what our next free database reference number is.
If we need to recycle a GARBAGE object, return the object to recycle
Otherwise, return the first free dbref.
"""
# First we'll see if there's an object of type 6 (GARBAGE) that we
# can recycle.
nextfree = Object.objects.filter(type__exact=defines_global.OTYPE_GARBAGE)
if nextfree:
# We've got at least one garbage object to recycle.
return nextfree.id
else:
# No garbage to recycle, find the highest dbnum and increment it
# for our next free.
return int(Object.objects.order_by('-id')[0].id + 1)
def global_object_name_search(ostring, exact_match=False):
"""
Searches through all objects for a name match.
"""
if exact_match:
return Object.objects.filter(name__iexact=ostring).exclude(type=defines_global.OTYPE_GARBAGE)
else:
return Object.objects.filter(name__icontains=ostring).exclude(type=defines_global.OTYPE_GARBAGE)
def list_search_object_namestr(searchlist, ostring, dbref_only=False, limit_types=False, match_type="fuzzy"):
"""
Iterates through a list of objects and returns a list of
name matches.
searchlist: (List of Objects) The objects to perform name comparisons on.
ostring: (string) The string to match against.
dbref_only: (bool) Only compare dbrefs.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
if dbref_only:
if limit_types:
return [prospect for prospect in searchlist if prospect.dbref_match(ostring) and prospect.type in limit_types]
else:
return [prospect for prospect in searchlist if prospect.dbref_match(ostring)]
else:
if limit_types:
return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type) and prospect.type in limit_types]
else:
return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)]
def standard_plr_objsearch(session, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
"""
Perform a standard object search via a player session, handling multiple
results and lack thereof gracefully.
session: (SessionProtocol) Reference to the player's session.
ostring: (str) The string to match object names against.
"""
pobject = session.get_pobject()
results = local_and_global_search(pobject, ostring, search_contents=search_contents, search_location=search_location, dbref_only=dbref_only, limit_types=limit_types)
if len(results) > 1:
session.msg("More than one match found (please narrow target):")
for result in results:
session.msg(" %s" % (result.get_name(),))
return False
elif len(results) == 0:
session.msg("I don't see that here.")
return False
else:
return results[0]
def object_totals():
"""
Returns a dictionary with database object totals.
"""
dbtotals = {}
dbtotals["objects"] = Object.objects.count()
dbtotals["things"] = Object.objects.filter(type=defines_global.OTYPE_THING).count()
dbtotals["exits"] = Object.objects.filter(type=defines_global.OTYPE_EXIT).count()
dbtotals["rooms"] = Object.objects.filter(type=defines_global.OTYPE_ROOM).count()
dbtotals["garbage"] = Object.objects.filter(type=defines_global.OTYPE_GARBAGE).count()
dbtotals["players"] = Object.objects.filter(type=defines_global.OTYPE_PLAYER).count()
return dbtotals
def alias_search(searcher, ostring):
"""
Search players by alias. Returns a list of objects whose "ALIAS" attribute
exactly (not case-sensitive) matches ostring.
searcher: (Object) The object doing the searching.
ostring: (string) The alias string to search for.
"""
search_query = ''.join(ostring)
results = Attribute.objects.select_related().filter(attr_name__exact="ALIAS").filter(attr_value__iexact=ostring)
return [prospect.get_object() for prospect in results if prospect.get_object().is_player()]
def player_name_search(search_string):
"""
Combines an alias and global search for a player's name. If there are
no alias matches, do a global search limiting by type PLAYER.
search_string: (string) The name string to search for.
"""
# Handle the case where someone might have started the search_string
# with a *
if search_string.startswith('*') is True:
search_string = search_string[1:]
# Use Q objects to build complex OR query to look at either
# the player name or ALIAS attribute
player_filter = Q(name__iexact=search_string)
alias_filter = Q(attribute__attr_name__exact="ALIAS") & \
Q(attribute__attr_value__iexact=search_string)
player_matches = Object.objects.filter(
player_filter | alias_filter).filter(
type=defines_global.OTYPE_PLAYER).distinct()
try:
return player_matches[0]
except IndexError:
return None
def dbref_search(dbref_string, limit_types=False):
"""
Searches for a given dbref.
dbref_number: (string) The dbref to search for
limit_types: (list of int) A list of Object type numbers to filter by.
"""
if not is_dbref(dbref_string):
return None
dbref_string = dbref_string[1:]
dbref_matches = Object.objects.filter(id=dbref_string).exclude(
type=defines_global.OTYPE_GARBAGE)
# Check for limiters
if limit_types is not False:
for limiter in limit_types:
dbref_matches.filter(type=limiter)
try:
return dbref_matches[0]
except IndexError:
return None
def local_and_global_search(searcher, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
"""
Searches an object's location then globally for a dbref or name match.
searcher: (Object) The object performing the search.
ostring: (string) The string to compare names against.
search_contents: (bool) While true, check the contents of the searcher.
search_location: (bool) While true, check the searcher's surroundings.
dbref_only: (bool) Only compare dbrefs.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
search_query = ''.join(ostring)
# This is a global dbref search. Not applicable if we're only searching
# searcher's contents/locations, dbref comparisons for location/contents
# searches are handled by list_search_object_namestr() below.
if is_dbref(ostring):
search_num = search_query[1:]
dbref_match = dbref_search(search_num, limit_types)
if dbref_match is not None:
return [dbref_match]
# If the search string is one of the following, return immediately with
# the appropriate result.
if searcher.get_location().dbref_match(ostring) or ostring == 'here':
return [searcher.get_location()]
elif ostring == 'me' and searcher:
return [searcher]
if search_query[0] == "*":
# Player search- gotta search by name or alias
search_target = search_query[1:]
player_match = player_name_search(search_target)
if player_match is not None:
return [player_match]
local_matches = []
# Handle our location/contents searches. list_search_object_namestr() does
# name and dbref comparisons against search_query.
if search_contents:
local_matches += list_search_object_namestr(searcher.get_contents(), search_query, limit_types)
if search_location:
local_matches += list_search_object_namestr(searcher.get_location().get_contents(), search_query, limit_types=limit_types)
return local_matches
def is_dbref(dbstring):
"""
Is the input a well-formed dbref number?
"""
try:
number = int(dbstring[1:])
except ValueError:
return False
if not dbstring.startswith("#"):
return False
elif number < 1:
return False
else:
return True
def get_user_from_email(uemail):
"""
Returns a player's User object when given an email address.
"""
return User.objects.filter(email__iexact=uemail)
def get_object_from_dbref(dbref):
"""
Returns an object when given a dbref.
"""
return Object.objects.get(id=dbref)
def create_object(odat):
"""
Create a new object. odat is a dictionary that contains the following keys.
REQUIRED KEYS:
* type: Integer representing the object's type.
* name: The name of the new object.
* location: Reference to another object for the new object to reside in.
* owner: The creator of the object.
OPTIONAL KEYS:
* home: Reference to another object to home to. If not specified, use
location key for home.
"""
next_dbref = get_nextfree_dbnum()
new_object = Object()
new_object.id = next_dbref
new_object.type = odat["type"]
new_object.set_name(odat["name"])
# If this is a player, we don't want him owned by anyone.
# The get_owner() function will return that the player owns
# himself.
if odat["type"] == 1:
new_object.owner = None
new_object.zone = None
else:
new_object.owner = odat["owner"]
if new_object.get_owner().get_zone():
new_object.zone = new_object.get_owner().get_zone()
# If we have a 'home' key, use that for our home value. Otherwise use
# the location key.
if odat.has_key("home"):
new_object.home = odat["home"]
else:
if new_object.is_exit():
new_object.home = None
else:
new_object.home = odat["location"]
new_object.save()
# Rooms have a NULL location.
if not new_object.is_room():
new_object.move_to(odat['location'])
return new_object
def create_user(cdat, uname, email, password):
"""
Handles the creation of new users.
"""
session = cdat['session']
server = cdat['server']
start_room = int(ConfigValue.objects.get_configvalue('player_dbnum_start'))
start_room_obj = get_object_from_dbref(start_room)
# The user's entry in the User table must match up to an object
# on the object table. The id's are the same, we need to figure out
# the next free unique ID to use and make sure the two entries are
# the same number.
uid = get_nextfree_dbnum()
print 'UID', uid
# If this is an object, we know to recycle it since it's garbage. We'll
# pluck the user ID from it.
if not str(uid).isdigit():
uid = uid.id
print 'UID2', uid
user = User.objects.create_user(uname, email, password)
# It stinks to have to do this but it's the only trivial way now.
user.save()
# We can't use the user model to change the id because of the way keys
# are handled, so we actually need to fall back to raw SQL. Boo hiss.
cursor = connection.cursor()
cursor.execute("UPDATE auth_user SET id=%d WHERE id=%d" % (uid, user.id))
# Grab the user object again since we've changed it and the old reference
# is no longer valid.
user = User.objects.get(id=uid)
# Create a player object of the same ID in the Objects table.
odat = {"id": uid, "name": uname, "type": 1, "location": start_room_obj, "owner": None}
user_object = create_object(odat)
# Activate the player's session and set them loose.
session.login(user)
print 'Registration: %s' % (session,)
session.msg("Welcome to %s, %s.\n\r" % (
ConfigValue.objects.get_configvalue('site_name'),
session.get_pobject().get_name(show_dbref=False)))

View file

@ -1,15 +1,19 @@
import time, sys """
This module contains classes related to Sessions. session_mgr has the things
needed to manage them.
"""
import time
import sys
from datetime import datetime from datetime import datetime
from django.utils import simplejson
from twisted.conch.telnet import StatefulTelnetProtocol from twisted.conch.telnet import StatefulTelnetProtocol
from django.utils import simplejson
from django.contrib.auth.models import User from django.contrib.auth.models import User
from apps.objects.models import Object from apps.objects.models import Object
from apps.config.models import ConnectScreen, ConfigValue from apps.config.models import ConnectScreen, ConfigValue
import cmdhandler import cmdhandler
import functions_db
import functions_general import functions_general
import functions_log import functions_log
import session_mgr import session_mgr

0
src/__init__.py Normal file
View file

11
src/exceptions_generic.py Normal file
View file

@ -0,0 +1,11 @@
"""
This module contains exceptions used throughout the server
"""
class GenericException(Exception):
"""
The custom exception class from which all other exceptions are derived.
"""
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)

19
src/flags.py Normal file
View file

@ -0,0 +1,19 @@
"""
Everything related to flags and flag management.
"""
import defines_global
def is_unsavable_flag(flagname):
"""
Returns TRUE if the flag is an unsavable flag.
"""
return flagname.upper() in defines_global.NOSAVE_FLAGS
def is_modifiable_flag(flagname):
"""
Check to see if a particular flag is modifiable.
"""
if flagname.upper() not in defines_global.NOSET_FLAGS:
return True
else:
return False