Move path and link_name related functions and regex patterns to a new
soc/logic/path_linkname.py module, and fix all dependencies. path/link_name
functionality is becoming the generic way to identify entities in the Datastore
in a URL-compatible way.
--- a/app/soc/logic/document.py Wed Oct 01 20:48:58 2008 +0000
+++ b/app/soc/logic/document.py Wed Oct 01 20:52:39 2008 +0000
@@ -19,6 +19,7 @@
__authors__ = [
'"Pawel Solyga" <pawel.solyga@gmail.com>',
+ '"Todd Larsen" <tlarsen@google.com>',
]
@@ -36,24 +37,6 @@
import soc.models.work
-WORK_PATH_LINKNAME_REGEX = re.compile(key_name.WORK_PATH_LINKNAME_PATTERN)
-
-def getPartsFromPath(path):
- """Splits path string into partial_path and link_name.
-
- Returns:
- {'partial_path': 'everything/but',
- 'link_name': 'link_name'}
- or {} (empty dict) if string did not match WORK_PATH_LINKNAME_PATTERN.
- """
- path_linkname_match = WORK_PATH_LINKNAME_REGEX.match(path)
-
- if not path_linkname_match:
- return {}
-
- return path_linkname_match.groupdict()
-
-
def getDocument(path, link_name=None):
"""Returns Document entity for a given path, or None if not found.
--- a/app/soc/logic/key_name.py Wed Oct 01 20:48:58 2008 +0000
+++ b/app/soc/logic/key_name.py Wed Oct 01 20:52:39 2008 +0000
@@ -23,27 +23,7 @@
]
-# start with ASCII digit or lowercase
-# (additional ASCII digit or lowercase
-# -OR-
-# underscore and ASCII digit or lowercase)
-# zero or more of OR group
-LINKNAME_PATTERN_CORE = r'[0-9a-z](?:[0-9a-z]|_[0-9a-z])*'
-
-LINKNAME_PATTERN = r'^%s$' % LINKNAME_PATTERN_CORE
-LINKNAME_ARG_PATTERN = r'(?P<linkname>%s)' % LINKNAME_PATTERN_CORE
-
-
-# partial path is multiple linkname chunks,
-# each separated by a trailing /
-# (at least 1)
-# followed by a single linkname with no trailing /
-WORK_PATH_LINKNAME_ARGS_PATTERN = (
- r'(?P<partial_path>%(linkname)s(?:/%(linkname)s)*)/'
- '(?P<linkname>%(linkname)s)' % {
- 'linkname': LINKNAME_PATTERN_CORE})
-
-WORK_PATH_LINKNAME_PATTERN = r'^%s$' % WORK_PATH_LINKNAME_ARGS_PATTERN
+from soc.logic import path_linkname
class Error(Exception):
@@ -56,45 +36,6 @@
return '%s.%s' % (cls.__module__, cls.__name__)
-def combinePath(path_parts):
- """Returns path components combined into a single string.
-
- Args:
- path_parts: a single path string, or a list of path part strings,
- or a nested list of path part strings (where the zeroeth element in
- the list is itself a list); for example:
- 'a/complete/path/in/one/string'
- ['some', 'path', 'parts']
- [['path', 'parts', 'and', 'a'], 'link name']
-
- Returns:
- None if path_parts is False (None, empty string, etc.) or if
- any list elements are False (an empty list, empty string, etc.);
- otherwise, the combined string with the necessary separators.
- """
- if not path_parts:
- # completely empty input, so return early
- return None
-
- if not isinstance(path_parts, (list, tuple)):
- # a single path string, so just return it as-is (nothing to do)
- return path_parts
-
- flattened_parts = []
-
- for part in path_parts:
- if not part:
- # encountered a "False" element, which invalidates everything else
- return None
-
- if isinstance(part, (list, tuple)):
- flattened_parts.extend(part)
- else:
- flattened_parts.append(part)
-
- return '/'.join(flattened_parts)
-
-
def nameDocument(partial_path, link_name=None):
"""Returns a Document key name constructed from a path and link name.
@@ -114,7 +55,7 @@
if link_name:
path.append(link_name)
- path = combinePath(path)
+ path = path_linkname.combinePath(path)
if not path:
raise Error('"path" must be non-False: "%s"' % path)
@@ -170,7 +111,7 @@
Error if sponsor_ln, program_ln, and link_Name combine to produce
a "False" path (None, empty string, etc.)
"""
- path = combinePath([[sponsor_ln, program_ln], link_name])
+ path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name])
if not path:
raise Error('"path" must be non-False: "%s"' % path)
@@ -190,7 +131,7 @@
Error if sponsor_ln, program_ln, and link_Name combine to produce
a "False" path (None, empty string, etc.)
"""
- path = combinePath([[sponsor_ln, program_ln], link_name])
+ path = path_linkname.combinePath([[sponsor_ln, program_ln], link_name])
if not path:
raise Error('"path" must be non-False: "%s"' % path)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/logic/path_linkname.py Wed Oct 01 20:52:39 2008 +0000
@@ -0,0 +1,103 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Path and link name manipulation functions.
+"""
+
+__authors__ = [
+ '"Todd Larsen" <tlarsen@google.com>',
+ ]
+
+
+import re
+
+
+# start with ASCII digit or lowercase
+# (additional ASCII digit or lowercase
+# -OR-
+# underscore and ASCII digit or lowercase)
+# zero or more of OR group
+LINKNAME_PATTERN_CORE = r'[0-9a-z](?:[0-9a-z]|_[0-9a-z])*'
+LINKNAME_ARG_PATTERN = r'(?P<linkname>%s)' % LINKNAME_PATTERN_CORE
+LINKNAME_PATTERN = r'^%s$' % LINKNAME_PATTERN_CORE
+LINKNAME_REGEX = re.compile(LINKNAME_PATTERN)
+
+# partial path is multiple linkname chunks,
+# each separated by a trailing /
+# (at least 1)
+# followed by a single linkname with no trailing /
+PATH_LINKNAME_ARGS_PATTERN = (
+ r'(?P<partial_path>%(linkname)s(?:/%(linkname)s)*)/'
+ '(?P<linkname>%(linkname)s)' % {
+ 'linkname': LINKNAME_PATTERN_CORE})
+
+PATH_LINKNAME_PATTERN = r'^%s$' % PATH_LINKNAME_ARGS_PATTERN
+PATH_LINKNAME_REGEX = re.compile(PATH_LINKNAME_PATTERN)
+
+
+def getPartsFromPath(path):
+ """Splits path string into partial_path and link_name.
+
+ Returns:
+ {'partial_path': 'everything/but',
+ 'link_name': 'link_name'}
+ or {} (empty dict) if string did not match PATH_LINKNAME_PATTERN.
+ """
+ path_linkname_match = PATH_LINKNAME_REGEX.match(path)
+
+ if not path_linkname_match:
+ return {}
+
+ return path_linkname_match.groupdict()
+
+
+def combinePath(path_parts):
+ """Returns path components combined into a single string.
+
+ Args:
+ path_parts: a single path string, or a list of path part strings,
+ or a nested list of path part strings (where the zeroeth element in
+ the list is itself a list); for example:
+ 'a/complete/path/in/one/string'
+ ['some', 'path', 'parts']
+ [['path', 'parts', 'and', 'a'], 'link name']
+
+ Returns:
+ None if path_parts is False (None, empty string, etc.) or if
+ any list elements are False (an empty list, empty string, etc.);
+ otherwise, the combined string with the necessary separators.
+ """
+ if not path_parts:
+ # completely empty input, so return early
+ return None
+
+ if not isinstance(path_parts, (list, tuple)):
+ # a single path string, so just return it as-is (nothing to do)
+ return path_parts
+
+ flattened_parts = []
+
+ for part in path_parts:
+ if not part:
+ # encountered a "False" element, which invalidates everything else
+ return None
+
+ if isinstance(part, (list, tuple)):
+ flattened_parts.extend(part)
+ else:
+ flattened_parts.append(part)
+
+ return '/'.join(flattened_parts)
--- a/app/soc/logic/validate.py Wed Oct 01 20:48:58 2008 +0000
+++ b/app/soc/logic/validate.py Wed Oct 01 20:52:39 2008 +0000
@@ -28,6 +28,8 @@
import feedparser
+from soc.logic import path_linkname
+
def isFeedURLValid(feed_url=None):
"""Returns True if provided url is valid ATOM or RSS.
@@ -44,25 +46,12 @@
return False
-LINKNAME_PATTERN = r'''(?x)
- ^
- [0-9a-z] # start with ASCII digit or lowercase
- (
- [0-9a-z] # additional ASCII digit or lowercase
- | # -OR-
- _[0-9a-z] # underscore and ASCII digit or lowercase
- )* # zero or more of OR group
- $
-'''
-
-LINKNAME_REGEX = re.compile(LINKNAME_PATTERN)
-
def isLinkNameFormatValid(link_name):
"""Returns True if link_name is in a valid format.
Args:
link_name: link name used in URLs for identification
"""
- if LINKNAME_REGEX.match(link_name):
+ if path_linkname.LINKNAME_REGEX.match(link_name):
return True
return False
\ No newline at end of file
--- a/app/soc/views/site/docs/edit.py Wed Oct 01 20:48:58 2008 +0000
+++ b/app/soc/views/site/docs/edit.py Wed Oct 01 20:52:39 2008 +0000
@@ -29,8 +29,8 @@
from django.utils.translation import ugettext_lazy
from soc.logic import document
-from soc.logic import key_name
from soc.logic import out_of_band
+from soc.logic import path_linkname
from soc.logic.site import id_user
from soc.views import simple
from soc.views.helpers import custom_widgets
@@ -76,7 +76,10 @@
Args:
request: the standard django request object
- path: the Document's site-unique "path" extracted from the URL
+ partial_path: the Document's site-unique "path" extracted from the URL,
+ minus the trailing link_name
+ link_name: the last portion of the Document's site-unique "path"
+ extracted from the URL
template: the "sibling" template (or a search list of such templates)
from which to construct the public.html template name (or names)
@@ -115,7 +118,7 @@
doc = None # assume that no Document entity will be found
- path = key_name.combinePath([partial_path, linkname])
+ path = path_linkname.combinePath([partial_path, linkname])
# try to fetch Document entity corresponding to path if one exists
try:
@@ -145,7 +148,7 @@
if not doc:
return http.HttpResponseRedirect('/')
- new_path = key_name.combinePath([new_partial_path, new_linkname])
+ new_path = path_linkname.combinePath([new_partial_path, new_linkname])
# redirect to new /site/docs/edit/new_path?s=0
# (causes 'Profile saved' message to be displayed)
@@ -263,8 +266,7 @@
if not doc:
return http.HttpResponseRedirect('/')
- new_path = key_name.combinePathAndLinkName(
- new_partial_path, new_linkname)
+ new_path = path_linkname.combinePath([new_partial_path, new_linkname])
# redirect to new /site/docs/edit/new_path?s=0
# (causes 'Profile saved' message to be displayed)