[CalendarServer-changes] [12363] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:22:00 PDT 2014
Revision: 12363
http://trac.calendarserver.org//changeset/12363
Author: cdaboo at apple.com
Date: 2014-01-16 14:01:41 -0800 (Thu, 16 Jan 2014)
Log Message:
-----------
Whitespace.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/platform/darwin/od/dsattributes.py
CalendarServer/trunk/calendarserver/platform/darwin/od/dsquery.py
CalendarServer/trunk/calendarserver/platform/darwin/od/odframework.py
CalendarServer/trunk/calendarserver/platform/darwin/od/opendirectory.py
CalendarServer/trunk/calendarserver/platform/darwin/od/setup_directory.py
CalendarServer/trunk/calendarserver/platform/darwin/od/setup_testusers.py
CalendarServer/trunk/calendarserver/platform/darwin/od/test/test_opendirectory.py
CalendarServer/trunk/calendarserver/platform/darwin/wiki.py
CalendarServer/trunk/calendarserver/provision/test/test_root.py
CalendarServer/trunk/calendarserver/push/applepush.py
CalendarServer/trunk/calendarserver/push/util.py
CalendarServer/trunk/calendarserver/tap/__init__.py
CalendarServer/trunk/calendarserver/tap/cfgchild.py
CalendarServer/trunk/calendarserver/tap/profiling.py
CalendarServer/trunk/calendarserver/tap/test/test_caldav.py
CalendarServer/trunk/calendarserver/tools/agent.py
CalendarServer/trunk/calendarserver/tools/ampnotifications.py
CalendarServer/trunk/calendarserver/tools/backup_pg.py
CalendarServer/trunk/calendarserver/tools/bootstrapdatabase.py
CalendarServer/trunk/calendarserver/tools/calverify_diff.py
CalendarServer/trunk/calendarserver/tools/changeip_calendar.py
CalendarServer/trunk/calendarserver/tools/config.py
CalendarServer/trunk/calendarserver/tools/icalsplit.py
CalendarServer/trunk/calendarserver/tools/managepostgres.py
CalendarServer/trunk/calendarserver/tools/migrate.py
CalendarServer/trunk/calendarserver/tools/notifications.py
CalendarServer/trunk/calendarserver/tools/principals.py
CalendarServer/trunk/calendarserver/tools/resources.py
CalendarServer/trunk/calendarserver/tools/shell/cmd.py
CalendarServer/trunk/calendarserver/tools/shell/terminal.py
CalendarServer/trunk/calendarserver/tools/shell/test/test_cmd.py
CalendarServer/trunk/calendarserver/tools/shell/vfs.py
CalendarServer/trunk/calendarserver/tools/tables.py
CalendarServer/trunk/calendarserver/tools/test/test_agent.py
CalendarServer/trunk/calendarserver/tools/test/test_config.py
CalendarServer/trunk/calendarserver/tools/test/test_gateway.py
CalendarServer/trunk/calendarserver/tools/test/test_resources.py
CalendarServer/trunk/calendarserver/tools/test/test_util.py
CalendarServer/trunk/calendarserver/webcal/resource.py
CalendarServer/trunk/calendarserver/webcal/test/test_resource.py
CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
CalendarServer/trunk/twistedcaldav/directory/calendar.py
CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py
CalendarServer/trunk/twistedcaldav/directory/digest.py
CalendarServer/trunk/twistedcaldav/directory/internal.py
CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
CalendarServer/trunk/twistedcaldav/directory/resourceinfo.py
CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
CalendarServer/trunk/twistedcaldav/directory/util.py
CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/idav.py
CalendarServer/trunk/txdav/xml/base.py
CalendarServer/trunk/txdav/xml/element.py
CalendarServer/trunk/txdav/xml/parser.py
CalendarServer/trunk/txdav/xml/parser_base.py
CalendarServer/trunk/txdav/xml/parser_etree.py
CalendarServer/trunk/txdav/xml/parser_sax.py
CalendarServer/trunk/txdav/xml/rfc2518.py
CalendarServer/trunk/txdav/xml/rfc3253.py
CalendarServer/trunk/txdav/xml/rfc3744.py
CalendarServer/trunk/txdav/xml/rfc4331.py
CalendarServer/trunk/txdav/xml/rfc5397.py
CalendarServer/trunk/txdav/xml/rfc5842.py
CalendarServer/trunk/txdav/xml/rfc5995.py
CalendarServer/trunk/txdav/xml/test/test_base.py
CalendarServer/trunk/txdav/xml/test/test_xml.py
CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/dsattributes.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/dsattributes.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/dsattributes.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -21,22 +21,22 @@
# Specific match types
-eDSExact = 0x2001
-eDSStartsWith = 0x2002
-eDSEndsWith = 0x2003
-eDSContains = 0x2004
+eDSExact = 0x2001
+eDSStartsWith = 0x2002
+eDSEndsWith = 0x2003
+eDSContains = 0x2004
-eDSLessThan = 0x2005
-eDSGreaterThan = 0x2006
-eDSLessEqual = 0x2007
-eDSGreaterEqual = 0x2008
+eDSLessThan = 0x2005
+eDSGreaterThan = 0x2006
+eDSLessEqual = 0x2007
+eDSGreaterEqual = 0x2008
# Specific Record Type Constants
"""
DirectoryService Specific Record Type Constants
"""
-
+
"""
kDSStdRecordTypeAccessControls
Record type that contains directory access control directives.
@@ -129,7 +129,7 @@
"""
kDSStdRecordTypeFileMakerServers
- FileMaker servers record type. Describes available FileMaker servers,
+ FileMaker servers record type. Describes available FileMaker servers,
used for service discovery.
"""
kDSStdRecordTypeFileMakerServers = "dsRecTypeStandard:FileMakerServers"
@@ -399,8 +399,8 @@
NOTE #2: Attributes in the model are available for records and directory nodes.
"""
-
+
# Single Valued Specific Attribute Type Constants
@@ -458,7 +458,7 @@
"""
kDS1AttrBootFile
- Attribute type in host or machine records for the name of the
+ Attribute type in host or machine records for the name of the
kernel that this machine will use by default when NetBooting.
"""
kDS1AttrBootFile = "dsAttrTypeStandard:BootFile"
@@ -480,8 +480,8 @@
"""
kDS1AttrCapacity
- Attribute type for the capacity of a resource.
- found in resource records (kDSStdRecordTypeResources).
+ Attribute type for the capacity of a resource.
+ found in resource records (kDSStdRecordTypeResources).
Example: 50
"""
kDS1AttrCapacity = "dsAttrTypeStandard:Capacity"
@@ -514,14 +514,14 @@
"""
kDS1AttrContactGUID
- Attribute type for the contact GUID of a group.
- found in group records (kDSStdRecordTypeGroups).
+ Attribute type for the contact GUID of a group.
+ found in group records (kDSStdRecordTypeGroups).
"""
kDS1AttrContactGUID = "dsAttrTypeStandard:ContactGUID"
"""
kDS1AttrContactPerson
- Attribute type for the contact person of the machine.
+ Attribute type for the contact person of the machine.
Found in host or machine records.
"""
kDS1AttrContactPerson = "dsAttrTypeStandard:ContactPerson"
@@ -535,7 +535,7 @@
"""
kDS1AttrCrossCertificatePair
- Attribute containing the binary of a pair of certificates which
+ Attribute containing the binary of a pair of certificates which
verify each other. Both certificates have the same level of authority.
Usually found in kDSStdRecordTypeCertificateAuthority records.
"""
@@ -587,7 +587,7 @@
"""
kDS1AttrGeneratedUID
- Used for 36 character (128 bit) unique ID. Usually found in user,
+ Used for 36 character (128 bit) unique ID. Usually found in user,
group, and computer records. An example value is "A579E95E-CDFE-4EBC-B7E7-F2158562170F".
The standard format contains 32 hex characters and four hyphen characters.
"""
@@ -678,7 +678,7 @@
"""
kDS1AttrMetaAutomountMap
- Used to query for kDSStdRecordTypeAutomount entries associated with a specific
+ Used to query for kDSStdRecordTypeAutomount entries associated with a specific
kDSStdRecordTypeAutomountMap.
"""
kDS1AttrMetaAutomountMap = "dsAttrTypeStandard:MetaAutomountMap"
@@ -728,15 +728,15 @@
"""
kDS1AttrOwner
- Attribute type for the owner of a record.
+ Attribute type for the owner of a record.
Typically the value is a LDAP distinguished name.
"""
kDS1AttrOwner = "dsAttrTypeStandard:Owner"
"""
kDS1AttrOwnerGUID
- Attribute type for the owner GUID of a group.
- found in group records (kDSStdRecordTypeGroups).
+ Attribute type for the owner GUID of a group.
+ found in group records (kDSStdRecordTypeGroups).
"""
kDS1AttrOwnerGUID = "dsAttrTypeStandard:OwnerGUID"
@@ -796,7 +796,7 @@
"""
kDS1AttrPrimaryComputerGUID
- Single-valued attribute that defines a primary computer of the computer group.
+ Single-valued attribute that defines a primary computer of the computer group.
added via extensible object for computer group record type (kDSStdRecordTypeComputerGroups)
"""
kDS1AttrPrimaryComputerGUID = "dsAttrTypeStandard:PrimaryComputerGUID"
@@ -809,7 +809,7 @@
"""
kDS1AttrPrimaryGroupID
- This is the 32 bit unique ID that represents the primary group
+ This is the 32 bit unique ID that represents the primary group
a user is part of, or the ID of a group. Format is a signed 32 bit integer
represented as a string.
"""
@@ -860,7 +860,7 @@
"""
kDS1AttrPrinterXRISupported
Multi-valued attribute that defines additional URIs supported by a printer.
- This is used when configuring a printer. This attribute is based on the IPP
+ This is used when configuring a printer. This attribute is based on the IPP
Printing Specification RFC and IETF IPP-LDAP Printer Record.
"""
kDSNAttrPrinterXRISupported = "dsAttrTypeStandard:PrinterXRISupported"
@@ -912,14 +912,14 @@
"""
kDS1AttrSMBHome
-
+
UNC address of Windows homedirectory mount point (\\server\\sharepoint).
"""
kDS1AttrSMBHome = "dsAttrTypeStandard:SMBHome"
"""
kDS1AttrSMBHomeDrive
-
+
Drive letter for homedirectory mount point.
"""
kDS1AttrSMBHomeDrive = "dsAttrTypeStandard:SMBHomeDrive"
@@ -977,7 +977,7 @@
"""
kDS1AttrSMBSID
SMB Security ID, stored as a string attribute of up to 64 bytes.
- Found in user, group, and computer records (kDSStdRecordTypeUsers,
+ Found in user, group, and computer records (kDSStdRecordTypeUsers,
kDSStdRecordTypeGroups, kDSStdRecordTypeComputers).
"""
kDS1AttrSMBSID = "dsAttrTypeStandard:SMBSID"
@@ -991,7 +991,7 @@
"""
kDS1AttrServiceType
Represents the service type for the service. This is the raw service type of the
- service. For example a service record type of kDSStdRecordTypeWebServer
+ service. For example a service record type of kDSStdRecordTypeWebServer
might have a service type of "http" or "https".
"""
kDS1AttrServiceType = "dsAttrTypeStandard:ServiceType"
@@ -1038,14 +1038,14 @@
kDS1AttrUserCertificate
Attribute containing the binary of the user's certificate.
Usually found in user records. The certificate is data which identifies a user.
- This data is attested to by a known party, and can be independently verified
+ This data is attested to by a known party, and can be independently verified
by a third party.
"""
kDS1AttrUserCertificate = "dsAttrTypeStandard:UserCertificate"
"""
kDS1AttrUserPKCS12Data
- Attribute containing binary data in PKCS #12 format.
+ Attribute containing binary data in PKCS #12 format.
Usually found in user records. The value can contain keys, certificates,
and other related information and is encrypted with a passphrase.
"""
@@ -1061,7 +1061,7 @@
kDS1AttrUserSMIMECertificate
Attribute containing the binary of the user's SMIME certificate.
Usually found in user records. The certificate is data which identifies a user.
- This data is attested to by a known party, and can be independently verified
+ This data is attested to by a known party, and can be independently verified
by a third party. SMIME certificates are often used for signed or encrypted
emails.
"""
@@ -1094,7 +1094,7 @@
"""
kDS1AttrWeblogURI
Single-valued attribute that defines the URI of a user's weblog.
- Usually found in user records (kDSStdRecordTypeUsers).
+ Usually found in user records (kDSStdRecordTypeUsers).
Example: http://example.com/blog/jsmith
"""
kDS1AttrWeblogURI = "dsAttrTypeStandard:WeblogURI"
@@ -1193,7 +1193,7 @@
"""
kDSNAttrBuilding
Represents the building name for a user or person record.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrBuilding = "dsAttrTypeStandard:Building"
@@ -1207,7 +1207,7 @@
"""
kDSNAttrCity
Usually, city for a user or person record.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrCity = "dsAttrTypeStandard:City"
@@ -1235,7 +1235,7 @@
"""
kDSNAttrCountry
Represents country of a record entry.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrCountry = "dsAttrTypeStandard:Country"
@@ -1243,7 +1243,7 @@
"""
kDSNAttrDepartment
Represents the department name of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrDepartment = "dsAttrTypeStandard:Department"
@@ -1263,7 +1263,7 @@
"""
kDSNAttrEMailContacts
multi-valued attribute that defines a record's custom email addresses .
- found in user records (kDSStdRecordTypeUsers).
+ found in user records (kDSStdRecordTypeUsers).
Example: home:johndoe at mymail.com
"""
kDSNAttrEMailContacts = "dsAttrTypeStandard:EMailContacts"
@@ -1271,7 +1271,7 @@
"""
kDSNAttrFaxNumber
Represents the FAX numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrFaxNumber = "dsAttrTypeStandard:FAXNumber"
@@ -1297,7 +1297,7 @@
"""
kDSNAttrGroupServices
xml-plist attribute that defines a group's services .
- found in group records (kDSStdRecordTypeGroups).
+ found in group records (kDSStdRecordTypeGroups).
"""
kDSNAttrGroupServices = "dsAttrTypeStandard:GroupServices"
@@ -1336,9 +1336,9 @@
"""
kDSNAttrIPAddressAndENetAddress
- A pairing of IPv4 or IPv6 addresses with Ethernet addresses
- (e.g., "10.1.1.1/00:16:cb:92:56:41"). Usually found on kDSStdRecordTypeComputers for use by
- services that need specific pairing of the two values. This should be in addition to
+ A pairing of IPv4 or IPv6 addresses with Ethernet addresses
+ (e.g., "10.1.1.1/00:16:cb:92:56:41"). Usually found on kDSStdRecordTypeComputers for use by
+ services that need specific pairing of the two values. This should be in addition to
kDSNAttrIPAddress, kDSNAttrIPv6Address and kDS1AttrENetAddress. This is necessary because not
all directories return attribute values in a guaranteed order.
"""
@@ -1347,15 +1347,15 @@
"""
kDSNAttrIPv6Address
IPv6 address expressed in the standard notation (e.g., "fe80::236:caff:fcc2:5641" )
- Usually found on kDSStdRecordTypeComputers, kDSStdRecordTypeHosts, and
+ Usually found on kDSStdRecordTypeComputers, kDSStdRecordTypeHosts, and
kDSStdRecordTypeMachines.
"""
kDSNAttrIPv6Address = "dsAttrTypeStandard:IPv6Address"
"""
kDSNAttrJPEGPhoto
- Used to store binary picture data in JPEG format.
- Usually found in user, people or group records (kDSStdRecordTypeUsers,
+ Used to store binary picture data in JPEG format.
+ Usually found in user, people or group records (kDSStdRecordTypeUsers,
kDSStdRecordTypePeople, kDSStdRecordTypeGroups).
"""
kDSNAttrJPEGPhoto = "dsAttrTypeStandard:JPEGPhoto"
@@ -1363,7 +1363,7 @@
"""
kDSNAttrJobTitle
Represents the job title of a user.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrJobTitle = "dsAttrTypeStandard:JobTitle"
@@ -1394,7 +1394,7 @@
"""
kDSNAttrMachineServes
- Attribute type in host or machine records for storing NetInfo
+ Attribute type in host or machine records for storing NetInfo
domains served.
"""
kDSNAttrMachineServes = "dsAttrTypeStandard:MachineServes"
@@ -1410,7 +1410,7 @@
"""
kDSNAttrMapURI
attribute that defines the URI of a user's location.
- Usually found in user records (kDSStdRecordTypeUsers).
+ Usually found in user records (kDSStdRecordTypeUsers).
Example: http://example.com/bldg1
"""
kDSNAttrMapURI = "dsAttrTypeStandard:MapURI"
@@ -1423,20 +1423,20 @@
"""
kDSNAttrMIME
- Data contained in this attribute type is a fully qualified MIME Type.
+ Data contained in this attribute type is a fully qualified MIME Type.
"""
kDSNAttrMIME = "dsAttrTypeStandard:MIME"
"""
kDSNAttrMember
- List of member records.
+ List of member records.
"""
kDSNAttrMember = "dsAttrTypeStandard:Member"
"""
kDSNAttrMobileNumber
Represents the mobile numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrMobileNumber = "dsAttrTypeStandard:MobileNumber"
@@ -1463,7 +1463,7 @@
"""
kDSNAttrNickName
Represents the nickname of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrNickName = "dsAttrTypeStandard:NickName"
@@ -1490,7 +1490,7 @@
"""
kDSNAttrPagerNumber
Represents the pager numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrPagerNumber = "dsAttrTypeStandard:PagerNumber"
@@ -1498,7 +1498,7 @@
"""
kDSNAttrPhoneContacts
multi-valued attribute that defines a record's custom phone numbers .
- found in user records (kDSStdRecordTypeUsers).
+ found in user records (kDSStdRecordTypeUsers).
Example: home fax:408-555-4444
"""
kDSNAttrPhoneContacts = "dsAttrTypeStandard:PhoneContacts"
@@ -1539,7 +1539,7 @@
kDSNAttrNamePrefix
Represents the title prefix of a user or person.
ie. Mr., Ms., Mrs., Dr., etc.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrNamePrefix = "dsAttrTypeStandard:NamePrefix"
@@ -1559,7 +1559,7 @@
"""
kDSNAttrRelationships
multi-valued attribute that defines the relationship to the record type .
- found in user records (kDSStdRecordTypeUsers).
+ found in user records (kDSStdRecordTypeUsers).
Example: brother:John
"""
kDSNAttrRelationships = "dsAttrTypeStandard:Relationships"
@@ -1572,8 +1572,8 @@
"""
kDSNAttrResourceType
- Attribute type for the kind of resource.
- found in resource records (kDSStdRecordTypeResources).
+ Attribute type for the kind of resource.
+ found in resource records (kDSStdRecordTypeResources).
Example: ConferenceRoom
"""
kDSNAttrResourceType = "dsAttrTypeStandard:ResourceType"
@@ -1593,7 +1593,7 @@
"""
kDSNAttrStreet
Represents the street address of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrStreet = "dsAttrTypeStandard:Street"
@@ -1602,7 +1602,7 @@
kDSNAttrNameSuffix
Represents the name suffix of a user or person.
ie. Jr., Sr., etc.
- Usually found in user or people records (kDSStdRecordTypeUsers or
+ Usually found in user or people records (kDSStdRecordTypeUsers or
kDSStdRecordTypePeople).
"""
kDSNAttrNameSuffix = "dsAttrTypeStandard:NameSuffix"
@@ -1837,7 +1837,7 @@
"""
Search Node attribute type Constants
"""
-
+
"""
kDS1AttrSearchPath
Search path used by the search node.
@@ -1891,4 +1891,3 @@
Retained only for backward compatibility.
"""
kDSNAttrCSPSearchPath = "dsAttrTypeStandard:CSPSearchPath"
-
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/dsquery.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/dsquery.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/dsquery.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -35,16 +35,19 @@
self.value = value
self.matchType = matchType
+
def generate(self):
return {
- dsattributes.eDSExact : "(%s=%s)",
- dsattributes.eDSStartsWith : "(%s=%s*)",
- dsattributes.eDSEndsWith : "(%s=*%s)",
- dsattributes.eDSContains : "(%s=*%s*)",
- dsattributes.eDSLessThan : "(%s<%s)",
- dsattributes.eDSGreaterThan : "(%s>%s)",
+ dsattributes.eDSExact: "(%s=%s)",
+ dsattributes.eDSStartsWith: "(%s=%s*)",
+ dsattributes.eDSEndsWith: "(%s=*%s)",
+ dsattributes.eDSContains: "(%s=*%s*)",
+ dsattributes.eDSLessThan: "(%s<%s)",
+ dsattributes.eDSGreaterThan : "(%s>%s)",
}.get(self.matchType, "(%s=*%s*)") % (self.attribute, self.value,)
+
+
class expression(object):
"""
Represents a query expression that includes a boolean operator, and a list
@@ -53,7 +56,7 @@
"""
AND = "&"
- OR = "|"
+ OR = "|"
NOT = "!"
def __init__(self, operator, subexpressions):
@@ -61,6 +64,7 @@
self.operator = operator
self.subexpressions = subexpressions
+
def generate(self):
result = ""
if self.operator == expression.NOT:
@@ -80,7 +84,7 @@
# Do some tests
-if __name__=='__main__':
+if __name__ == '__main__':
exprs = (
(expression(
expression.AND, (
@@ -106,26 +110,26 @@
)
), "(ServicesLocator=*GUID:VGUID:calendar*)"),
(expression(
- expression.NOT, match(dsattributes.kDSNAttrNickName, "", dsattributes.eDSStartsWith )
+ expression.NOT, match(dsattributes.kDSNAttrNickName, "", dsattributes.eDSStartsWith)
), "(!(" + dsattributes.kDSNAttrNickName + "=*))"),
(expression(
expression.AND, (
expression(
- expression.NOT, match(dsattributes.kDSNAttrNickName, "Billy", dsattributes.eDSContains )
+ expression.NOT, match(dsattributes.kDSNAttrNickName, "Billy", dsattributes.eDSContains)
),
expression(
- expression.NOT, match(dsattributes.kDSNAttrEMailAddress, "Billy", dsattributes.eDSContains )
+ expression.NOT, match(dsattributes.kDSNAttrEMailAddress, "Billy", dsattributes.eDSContains)
),
),
), "(&(!(" + dsattributes.kDSNAttrNickName + "=*Billy*))(!(" + dsattributes.kDSNAttrEMailAddress + "=*Billy*)))"),
(expression(
expression.NOT, expression(
expression.OR, (
- match(dsattributes.kDSNAttrNickName, "", dsattributes.eDSStartsWith ),
- match(dsattributes.kDSNAttrEMailAddress, "", dsattributes.eDSStartsWith ),
+ match(dsattributes.kDSNAttrNickName, "", dsattributes.eDSStartsWith),
+ match(dsattributes.kDSNAttrEMailAddress, "", dsattributes.eDSStartsWith),
),
),
- ), "(!(|("+dsattributes.kDSNAttrNickName+"=*)("+dsattributes.kDSNAttrEMailAddress+"=*)))"),
+ ), "(!(|(" + dsattributes.kDSNAttrNickName + "=*)(" + dsattributes.kDSNAttrEMailAddress + "=*)))"),
)
for expr, result in exprs:
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/odframework.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/odframework.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/odframework.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -5,4 +5,3 @@
frameworkPath=_objc.pathForFramework(
"/System/Library/Frameworks/OpenDirectory.framework"),
globals=globals())
-
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/opendirectory.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/opendirectory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/opendirectory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -84,6 +84,7 @@
self.node = node
self.nodeName = nodeName
+
def __str__(self):
return "OpenDirectory node: %s" % (self.nodeName)
@@ -96,6 +97,7 @@
# return caseInsensitiveEquivalents[matchType] if caseInsensitive else matchType
+
def recordToResult(record, encodings):
"""
Takes an ODRecord and turns it into a (recordName, attributesDictionary)
@@ -132,6 +134,7 @@
return (details.get(dsattributes.kDSNAttrRecordName, [None])[0], result)
+
def attributeNamesFromList(attributes):
"""
The attributes list can contain string names or tuples of the form (name,
@@ -152,6 +155,7 @@
return names, encodings
+
@autoPooled
def odInit(nodeName):
"""
@@ -216,6 +220,7 @@
raise ODNSError(error)
+
@autoPooled
def listAllRecordsWithAttributes_list(directory, recordType, attributes, count=0):
"""
@@ -265,6 +270,7 @@
raise ODNSError(error)
+
@autoPooled
def queryRecordsWithAttribute_list(directory, attr, value, matchType, casei, recordType, attributes, count=0):
"""
@@ -319,6 +325,7 @@
raise ODNSError(error)
+
@autoPooled
def queryRecordsWithAttributes_list(directory, compound, casei, recordType, attributes, count=0):
"""
@@ -372,6 +379,7 @@
raise ODNSError(error)
+
def getUserRecord(directory, user):
"""
Look up the record for the given user within the directory's node
@@ -404,6 +412,7 @@
raise ODNSError(error)
+
@autoPooled
def authenticateUserBasic(directory, nodeName, user, password):
"""
@@ -422,7 +431,7 @@
tries = NUM_TRIES
while tries:
- log.debug("Checking basic auth for user '{user}' (tries remaining: {tries})",
+ log.debug("Checking basic auth for user '{user}' (tries remaining: {tries})",
user=user, tries=tries)
result, error = record.verifyPassword_error_(password, None)
@@ -448,6 +457,7 @@
raise ODNSError(error)
+
@autoPooled
def authenticateUserDigest(directory, nodeName, user, challenge, response, method):
"""
@@ -472,7 +482,7 @@
user=user, tries=tries)
# TODO: what are these other return values?
- result, mystery1, mystery2, error = record.verifyExtendedWithAuthenticationType_authenticationItems_continueItems_context_error_(
+ result, _ignore_mystery1, _ignore_mystery2, error = record.verifyExtendedWithAuthenticationType_authenticationItems_continueItems_context_error_(
DIGEST_MD5,
[user, challenge, response, method],
None, None, None
@@ -499,6 +509,7 @@
raise ODNSError(error)
+
class ODError(Exception):
"""
Exceptions from DirectoryServices errors.
@@ -506,10 +517,12 @@
def __init__(self, msg, code):
self.message = (msg, code)
+
def __str__(self):
return "<OD Error %s %d>" % (self.message[0], self.message[1])
+
class ODNSError(ODError):
"""
Converts an NSError.
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/setup_directory.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/setup_directory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/setup_directory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -240,6 +240,8 @@
return records[0]
+
+
def createRecord(node, recordType, recordName, attrs):
record, error = node.createRecordWithRecordType_name_attributes_error_(
recordType,
@@ -251,6 +253,8 @@
raise ODError(error)
return record
+
+
def main():
try:
@@ -258,7 +262,7 @@
except GetoptError, e:
usage(e)
- for opt, arg in optargs:
+ for opt, _ignore_arg in optargs:
if opt in ("-h", "--help"):
usage()
@@ -373,6 +377,8 @@
print("")
+
+
class ODError(Exception):
def __init__(self, error):
self.message = (str(error), error.code())
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/setup_testusers.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/setup_testusers.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/setup_testusers.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -36,6 +36,7 @@
sys.exit(0)
+
def lookupRecordName(node, recordType, name):
query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
node,
@@ -59,6 +60,8 @@
return records[0]
+
+
def createRecord(node, recordType, recordName, attrs):
record, error = node.createRecordWithRecordType_name_attributes_error_(
recordType,
@@ -70,6 +73,8 @@
raise ODError(error)
return record
+
+
def main():
try:
@@ -77,7 +82,7 @@
except GetoptError, e:
usage(e)
- for opt, arg in optargs:
+ for opt, _ignore_arg in optargs:
if opt in ("-h", "--help"):
usage()
@@ -108,7 +113,7 @@
print("Creating users within %s:" % (nodeName,))
for i in xrange(99):
- j = i+1
+ j = i + 1
recordName = "user%02d" % (j,)
password = "user%02d" % (j,)
attrs = {
@@ -137,6 +142,7 @@
print("User %s already exists" % (recordName,))
+
class ODError(Exception):
def __init__(self, error):
self.message = (str(error), error.code())
Modified: CalendarServer/trunk/calendarserver/platform/darwin/od/test/test_opendirectory.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/od/test/test_opendirectory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/od/test/test_opendirectory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -48,17 +48,20 @@
print("Unable to import OpenDirectory framework")
+
def generateNonce():
c = tuple([random.randrange(sys.maxint) for _ in range(3)])
c = '%d%d%d' % c
return c
+
+
def getChallengeResponse(user, password, node, uri, method):
nonce = generateNonce()
ha1 = hashlib.md5("%s:%s:%s" % (user, node, password)).hexdigest()
ha2 = hashlib.md5("%s:%s" % (method, uri)).hexdigest()
- response = hashlib.md5("%s:%s:%s"% (ha1, nonce, ha2)).hexdigest()
+ response = hashlib.md5("%s:%s:%s" % (ha1, nonce, ha2)).hexdigest()
fields = {
'username': user,
@@ -135,7 +138,7 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.masterUsers:
+ for recordName, _ignore_info in setup_directory.masterUsers:
self.assertTrue(recordName in recordNames)
def test_listAllRecordsWithAttributes_list_local(self):
@@ -148,7 +151,7 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.localUsers:
+ for recordName, _ignore_info in setup_directory.localUsers:
self.assertTrue(recordName in recordNames)
@@ -333,9 +336,9 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.masterUsers:
+ for recordName, _ignore_info in setup_directory.masterUsers:
self.assertTrue(recordName in recordNames)
- for recordName, info in setup_directory.localUsers:
+ for recordName, _ignore_info in setup_directory.localUsers:
self.assertTrue(recordName in recordNames)
def test_queryRecordsWithAttribute_list_lastname_begins_insensitive_match_multitype(self):
@@ -358,9 +361,9 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.masterUsers:
+ for recordName, _ignore_info in setup_directory.masterUsers:
self.assertTrue(recordName in recordNames)
- for recordName, info in setup_directory.localUsers:
+ for recordName, _ignore_info in setup_directory.localUsers:
self.assertTrue(recordName in recordNames)
def test_queryRecordsWithAttribute_list_lastname_contains_insensitive_match(self):
@@ -378,9 +381,9 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.masterUsers:
+ for recordName, _ignore_info in setup_directory.masterUsers:
self.assertTrue(recordName in recordNames)
- for recordName, info in setup_directory.localUsers:
+ for recordName, _ignore_info in setup_directory.localUsers:
self.assertTrue(recordName in recordNames)
def test_queryRecordsWithAttribute_list_lastname_contains_insensitive_match_multitype(self):
@@ -403,9 +406,9 @@
count=0
)
recordNames = [x[0] for x in results]
- for recordName, info in setup_directory.masterUsers:
+ for recordName, _ignore_info in setup_directory.masterUsers:
self.assertTrue(recordName in recordNames)
- for recordName, info in setup_directory.localUsers:
+ for recordName, _ignore_info in setup_directory.localUsers:
self.assertTrue(recordName in recordNames)
def test_queryRecordsWithAttribute_list_email_begins_insensitive_match(self):
@@ -451,7 +454,6 @@
self.assertTrue("odtestamanda" in recordNames)
-
def test_queryRecordsWithAttribute_list_guid_exact_sensitive_match_master(self):
directory = opendirectory.odInit("/Search")
@@ -537,7 +539,6 @@
self.assertTrue("odtestalbert" in recordNames)
-
def test_queryRecordsWithAttribute_list_groupMembers_recordName_master(self):
directory = opendirectory.odInit("/Search")
@@ -659,7 +660,6 @@
recordNames = [x[0] for x in results]
self.assertTrue("odtestgrouptop" in recordNames)
-
results = opendirectory.queryRecordsWithAttribute_list(
directory,
dsattributes.kDSNAttrNestedGroups,
@@ -856,7 +856,7 @@
def test_result_types(self):
directory = opendirectory.odInit("/Search")
record = opendirectory.getUserRecord(directory, "odtestbill")
- name, data = opendirectory.recordToResult(record, {})
+ _ignore_name, data = opendirectory.recordToResult(record, {})
for value in data.values():
if isinstance(value, list):
for item in value:
@@ -925,7 +925,7 @@
([], {}), opendirectory.attributeNamesFromList(None)
)
self.assertEquals(
- (["a", "b"], {"b":"base64"}),
+ (["a", "b"], {"b": "base64"}),
opendirectory.attributeNamesFromList(["a", ("b", "base64")])
)
Modified: CalendarServer/trunk/calendarserver/platform/darwin/wiki.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/wiki.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/platform/darwin/wiki.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -52,6 +52,8 @@
else:
raise WebAuthError("Could not look up token: %s" % (token,))
+
+
def accessForUserToWiki(user, wiki, host="localhost", port=4444):
"""
Send a GET request to the wiki collabd service to retrieve the access level
@@ -72,6 +74,7 @@
return _getPage(url, host, port)
+
def _getPage(url, host, port):
"""
Fetch the body of the given url via HTTP, connecting to the given host
@@ -91,6 +94,8 @@
connect(GAIEndpoint(reactor, host, port), factory)
return factory.deferred
+
+
class WebAuthError(RuntimeError):
"""
Error in web auth
Modified: CalendarServer/trunk/calendarserver/provision/test/test_root.py
===================================================================
--- CalendarServer/trunk/calendarserver/provision/test/test_root.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/provision/test/test_root.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -41,6 +41,7 @@
def __init__(self, sacls=None):
self.sacls = sacls or {}
+
def __call__(self, username, service):
if service not in self.sacls:
return 1
@@ -50,6 +51,8 @@
return 1
+
+
class RootTests(TestCase):
def setUp(self):
@@ -127,7 +130,7 @@
class SACLTests(RootTests):
-
+
@inlineCallbacks
def test_noSacls(self):
"""
@@ -141,7 +144,7 @@
"GET",
"/principals/")
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
@@ -157,6 +160,7 @@
self.assertEquals(segments, [])
+
@inlineCallbacks
def test_inSacls(self):
"""
@@ -179,7 +183,7 @@
})
)
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
@@ -205,6 +209,7 @@
)
)
+
@inlineCallbacks
def test_notInSacls(self):
"""
@@ -227,17 +232,18 @@
})
)
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
try:
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
resrc.locateChild, request, ["principals"]
))
except HTTPError, e:
self.assertEquals(e.response.code, 403)
+
@inlineCallbacks
def test_unauthenticated(self):
"""
@@ -254,12 +260,12 @@
"/principals/"
)
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
try:
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
resrc.locateChild, request, ["principals"]
))
raise AssertionError(
@@ -268,6 +274,7 @@
except HTTPError, e:
self.assertEquals(e.response.code, 401)
+
@inlineCallbacks
def test_badCredentials(self):
"""
@@ -286,19 +293,18 @@
"Authorization": ["basic", "%s" % (
"dreid:dreid".encode("base64"),)]}))
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
try:
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
resrc.locateChild, request, ["principals"]
))
except HTTPError, e:
self.assertEquals(e.response.code, 401)
-
def test_DELETE(self):
def do_test(response):
response = IResponse(response)
@@ -310,6 +316,7 @@
request = SimpleRequest(self.site, "DELETE", "/")
return self.send(request, do_test)
+
def test_COPY(self):
def do_test(response):
response = IResponse(response)
@@ -322,10 +329,11 @@
self.site,
"COPY",
"/",
- headers=http_headers.Headers({"Destination":"/copy/"})
+ headers=http_headers.Headers({"Destination": "/copy/"})
)
return self.send(request, do_test)
+
def test_MOVE(self):
def do_test(response):
response = IResponse(response)
@@ -338,12 +346,14 @@
self.site,
"MOVE",
"/",
- headers=http_headers.Headers({"Destination":"/copy/"})
+ headers=http_headers.Headers({"Destination": "/copy/"})
)
return self.send(request, do_test)
+
+
class SACLCacheTests(RootTests):
-
+
class StubResponseCacheResource(object):
def __init__(self):
self.cache = {}
@@ -354,16 +364,18 @@
if str(request) in self.cache:
self.cacheHitCount += 1
return self.cache[str(request)]
-
-
+
+
def cacheResponseForRequest(self, request, response):
self.cache[str(request)] = response
return response
+
def setUp(self):
super(SACLCacheTests, self).setUp()
self.root.resource.responseCache = SACLCacheTests.StubResponseCacheResource()
+
def test_PROPFIND(self):
self.root.resource.useSacls = True
@@ -383,7 +395,7 @@
headers=http_headers.Headers({
'Authorization': ['basic', '%s' % ('dreid:dierd'.encode('base64'),)],
'Content-Type': 'application/xml; charset="utf-8"',
- 'Depth':'1',
+ 'Depth': '1',
}),
content=body
)
@@ -399,7 +411,7 @@
headers=http_headers.Headers({
'Authorization': ['basic', '%s' % ('dreid:dierd'.encode('base64'),)],
'Content-Type': 'application/xml; charset="utf-8"',
- 'Depth':'1',
+ 'Depth': '1',
}),
content=body
)
@@ -415,8 +427,10 @@
d = self.send(request, gotResponse1)
return d
+
+
class WikiTests(RootTests):
-
+
@inlineCallbacks
def test_oneTime(self):
"""
@@ -426,10 +440,10 @@
request = SimpleRequest(self.site, "GET", "/principals/")
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
self.root.locateChild, request, ["principals"]
))
- resrc, segments = (yield maybeDeferred(
+ resrc, _ignore_segments = (yield maybeDeferred(
resrc.locateChild, request, ["principals"]
))
self.assertTrue(request.checkedWiki)
Modified: CalendarServer/trunk/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/trunk/calendarserver/push/applepush.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/push/applepush.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -51,9 +51,9 @@
"""
Maps calendarserver.push.util.PushPriority values to APNS-specific values
"""
- low = ValueConstant(PushPriority.low.value)
+ low = ValueConstant(PushPriority.low.value)
medium = ValueConstant(PushPriority.medium.value)
- high = ValueConstant(PushPriority.high.value)
+ high = ValueConstant(PushPriority.high.value)
@@ -400,26 +400,26 @@
# Frame struct.pack format
# ! Network byte order
command = self.COMMAND_PROVIDER # B
- frameLength = ( # I
+ frameLength = (# I
# Item 1 (Device token)
- 1 + # Item number # B
- 2 + # Item length # H
+ 1 + # Item number # B
+ 2 + # Item length # H
32 + # device token # 32s
# Item 2 (Payload)
- 1 + # Item number # B
- 2 + # Item length # H
+ 1 + # Item number # B
+ 2 + # Item length # H
payloadLength + # the JSON payload # %d s
# Item 3 (Notification ID)
- 1 + # Item number # B
- 2 + # Item length # H
- 4 + # Notification ID # I
+ 1 + # Item number # B
+ 2 + # Item length # H
+ 4 + # Notification ID # I
# Item 4 (Expiration)
- 1 + # Item number # B
- 2 + # Item length # H
- 4 + # Expiration seconds since epoch # I
+ 1 + # Item number # B
+ 2 + # Item length # H
+ 4 + # Expiration seconds since epoch # I
# Item 5 (Priority)
- 1 + # Item number # B
- 2 + # Item length # H
+ 1 + # Item number # B
+ 2 + # Item length # H
1 # Priority # B
)
@@ -453,6 +453,7 @@
)
+
class APNProviderFactory(ReconnectingClientFactory):
log = Logger()
@@ -629,7 +630,7 @@
"""
for token in tokens:
tokenKeyPair = (token, key)
- for existingPair, timstamp, priority in self.queue:
+ for existingPair, _ignore_timstamp, priority in self.queue:
if tokenKeyPair == existingPair:
self.log.debug("APNProviderService has no connection; skipping duplicate: %s %s" % (token, key))
break # Already scheduled
Modified: CalendarServer/trunk/calendarserver/push/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/push/util.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/push/util.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -24,9 +24,9 @@
"""
Constants to use for push priorities
"""
- low = ValueConstant(1)
+ low = ValueConstant(1)
medium = ValueConstant(5)
- high = ValueConstant(10)
+ high = ValueConstant(10)
Modified: CalendarServer/trunk/calendarserver/tap/__init__.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/__init__.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tap/__init__.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -26,4 +26,3 @@
"profiling",
"util"
]
-
Modified: CalendarServer/trunk/calendarserver/tap/cfgchild.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/cfgchild.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tap/cfgchild.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -95,12 +95,12 @@
# Adjust the child's configuration to add all the relevant options for
# the store that won't be mentioned in the config file.
changedConfig = dict(
- EnableCalDAV = True,
- EnableCardDAV = True,
- LogID = logID,
- PIDFile = pidFile,
- MultiProcess = dict(
- ProcessCount = processCount
+ EnableCalDAV=True,
+ EnableCardDAV=True,
+ LogID=logID,
+ PIDFile=pidFile,
+ MultiProcess=dict(
+ ProcessCount=processCount
)
)
setupMemcached(self.config)
@@ -177,16 +177,16 @@
# until the call to spawn (and hence spawnProcess) below; otherwise
# that end of the socket will be closed and there will be nothing
# to inherit.
- poolskt = self.dispenser.dispense()
- poolfd = poolskt.fileno()
+ poolskt = self.dispenser.dispense()
+ poolfd = poolskt.fileno()
childFDs = {
0: "w", 1: "r", 2: "r", # behave like normal, but
poolfd: poolfd # bonus FD
}
- extra = dict(connectionPoolFD=poolfd)
+ extra = dict(connectionPoolFD=poolfd)
else:
childFDs = None
- extra = {}
+ extra = {}
controller = yield self.spawn(
AMP(), ChildConfigurator, childFDs=childFDs
)
@@ -201,6 +201,3 @@
**extra
)
returnValue(swapAMP(controller, here))
-
-
-
Modified: CalendarServer/trunk/calendarserver/tap/profiling.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/profiling.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tap/profiling.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -29,7 +29,8 @@
Run reactor under the cProfile profiler.
"""
try:
- import cProfile, pstats
+ import cProfile
+ import pstats
except ImportError, e:
self._reportImportError("cProfile", e)
Modified: CalendarServer/trunk/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/test/test_caldav.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tap/test/test_caldav.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -1473,24 +1473,29 @@
self.assertFalse(triggerFile.exists())
+
class StubStorageService(object):
def __init__(self):
self.hardStopCalled = False
+
def hardStop(self):
self.hardStopCalled = True
+
class StubReactor(object):
def __init__(self):
self.stopCalled = False
+
def stop(self):
self.stopCalled = True
+
class DataStoreMonitorTestCase(TestCase):
def test_monitor(self):
Modified: CalendarServer/trunk/calendarserver/tools/agent.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/agent.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/agent.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -34,7 +34,7 @@
from twisted.application.internet import StreamServerEndpointService
from twisted.cred.checkers import ICredentialsChecker
from twisted.cred.credentials import IUsernameHashedPassword
-from twisted.cred.error import UnauthorizedLogin
+from twisted.cred.error import UnauthorizedLogin
from twisted.cred.portal import IRealm, Portal
from twisted.internet.defer import inlineCallbacks, returnValue, succeed, fail
from twisted.internet.endpoints import AdoptedStreamServerEndpoint
@@ -69,6 +69,7 @@
self.node = node
self.directory = self.directoryModule.odInit(node)
+
def requestAvatarId(self, credentials):
record = self.directoryModule.getUserRecord(self.directory, credentials.username)
@@ -119,6 +120,7 @@
return fail(UnauthorizedLogin())
+
class CustomDigestCredentialFactory(DigestCredentialFactory):
"""
DigestCredentialFactory without qop, to interop with OD.
@@ -130,6 +132,7 @@
return result
+
class AgentRealm(object):
"""
Only allow a specified list of avatar IDs to access the site
@@ -144,6 +147,7 @@
self.root = root
self.allowedAvatarIds = allowedAvatarIds
+
def requestAvatar(self, avatarId, mind, *interfaces):
if IResource in interfaces:
if avatarId in self.allowedAvatarIds:
@@ -176,6 +180,7 @@
self.directory = directory
self.inactivityDetector = inactivityDetector
+
def render_POST(self, request):
"""
Take the body of the POST request and feed it to gateway.Runner();
@@ -217,8 +222,6 @@
-
-
def makeAgentService(store):
"""
Returns a service which will process GatewayAMPCommands, using a socket
@@ -229,9 +232,9 @@
"""
from twisted.internet import reactor
- sockets = getLaunchDSocketFDs()
+ sockets = getLaunchDSocketFDs()
fd = sockets["AgentSocket"][0]
-
+
family = socket.AF_INET
endpoint = AdoptedStreamServerEndpoint(reactor, fd, family)
@@ -321,12 +324,13 @@
class GatewayAMPCommand(amp.Command):
"""
- A command to be executed by gateway.Runner
+ A command to be executed by gateway.Runner
"""
arguments = [('command', amp.String())]
response = [('result', amp.String())]
+
class GatewayAMPProtocol(amp.AMP):
"""
Passes commands to gateway.Runner and returns the results
@@ -374,6 +378,7 @@
returnValue(dict(result=result))
+
class GatewayAMPFactory(Factory):
"""
Builds GatewayAMPProtocols
@@ -389,6 +394,7 @@
self.davRootResource = getRootResource(config, self.store)
self.directory = self.davRootResource.getDirectory()
+
def buildProtocol(self, addr):
return GatewayAMPProtocol(self.store, self.davRootResource,
self.directory)
Modified: CalendarServer/trunk/calendarserver/tools/ampnotifications.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/ampnotifications.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/ampnotifications.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -71,6 +71,7 @@
pass
+
def main():
try:
Modified: CalendarServer/trunk/calendarserver/tools/backup_pg.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/backup_pg.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/backup_pg.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -26,16 +26,16 @@
from twistedcaldav.config import config
from calendarserver.tools.util import loadConfig
-SIPP = "/Applications/Server.app/Contents/ServerRoot"
+SIPP = "/Applications/Server.app/Contents/ServerRoot"
if not os.path.exists(SIPP):
- SIPP = ""
-USERNAME = "caldav"
-DATABASENAME = "caldav"
-DUMPFILENAME = "db_backup"
+ SIPP = ""
+USERNAME = "caldav"
+DATABASENAME = "caldav"
+DUMPFILENAME = "db_backup"
-PSQL = "%s/usr/bin/psql" % (SIPP,)
-PGDUMP = "%s/usr/bin/pg_dump" % (SIPP,)
-PGSOCKETDIR = "/var/run/caldavd/PostgresSocket"
+PSQL = "%s/usr/bin/psql" % (SIPP,)
+PGDUMP = "%s/usr/bin/pg_dump" % (SIPP,)
+PGSOCKETDIR = "/var/run/caldavd/PostgresSocket"
def usage(e=None):
name = os.path.basename(sys.argv[0])
@@ -60,6 +60,7 @@
sys.exit(0)
+
def dumpData(dumpFile, verbose=False):
"""
Use pg_dump to dump data to dumpFile
@@ -90,6 +91,7 @@
)
+
def loadData(dumpFile, verbose=False):
"""
Use psql to load data from dumpFile
@@ -117,15 +119,18 @@
)
+
class BackupError(Exception):
pass
+
def error(s):
sys.stderr.write("%s\n" % (s,))
sys.exit(1)
+
def main():
try:
(optargs, args) = getopt(
Modified: CalendarServer/trunk/calendarserver/tools/bootstrapdatabase.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/bootstrapdatabase.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/bootstrapdatabase.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -21,16 +21,16 @@
import subprocess
import sys
-CONNECTNAME = "_postgres"
-USERNAME = "caldav"
-DATABASENAME = "caldav"
-PGSOCKETDIR = "/Library/Server/PostgreSQL For Server Services/Socket"
-SCHEMAFILE = "/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/lib/python/txdav/common/datastore/sql_schema/current.sql"
+CONNECTNAME = "_postgres"
+USERNAME = "caldav"
+DATABASENAME = "caldav"
+PGSOCKETDIR = "/Library/Server/PostgreSQL For Server Services/Socket"
+SCHEMAFILE = "/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/lib/python/txdav/common/datastore/sql_schema/current.sql"
# Executables:
-CREATEDB = "/Applications/Server.app/Contents/ServerRoot/usr/bin/createdb"
-CREATEUSER = "/Applications/Server.app/Contents/ServerRoot/usr/bin/createuser"
-PSQL = "/Applications/Server.app/Contents/ServerRoot/usr/bin/psql"
+CREATEDB = "/Applications/Server.app/Contents/ServerRoot/usr/bin/createdb"
+CREATEUSER = "/Applications/Server.app/Contents/ServerRoot/usr/bin/createuser"
+PSQL = "/Applications/Server.app/Contents/ServerRoot/usr/bin/psql"
def usage(e=None):
name = os.path.basename(sys.argv[0])
@@ -49,6 +49,8 @@
else:
sys.exit(0)
+
+
def createUser(verbose=False):
"""
Create the user which calendar server will use to access postgres.
@@ -84,6 +86,7 @@
)
+
def createDatabase(verbose=False):
"""
Create the database which calendar server will use within postgres.
@@ -116,6 +119,7 @@
)
+
def getSchemaVersion(verbose=False):
"""
Return the version number for the schema installed in the database.
@@ -153,6 +157,8 @@
)
return version
+
+
def installSchema(verbose=False):
"""
Install the calendar server database schema.
@@ -184,16 +190,21 @@
)
+
class BootstrapError(Exception):
pass
+
+
def error(s):
sys.stderr.write("%s\n" % (s,))
sys.exit(1)
+
+
def main():
try:
- (optargs, args) = getopt(
+ (optargs, _ignore_args) = getopt(
sys.argv[1:], "hv", [
"help",
"verbose",
@@ -204,7 +215,7 @@
verbose = False
- for opt, arg in optargs:
+ for opt, _ignore_arg in optargs:
if opt in ("-h", "--help"):
usage()
elif opt in ("-v", "--verbose"):
@@ -212,7 +223,6 @@
else:
raise NotImplementedError(opt)
-
# Create the calendar server database user within postgres
try:
newlyCreated = createUser(verbose=verbose)
@@ -252,12 +262,12 @@
required_version = int(found.group(1))
if version == required_version:
print("Latest schema version (%d) is installed" % (version,))
-
+
elif version == 0: # No schema installed
installSchema(verbose=verbose)
version = getSchemaVersion(verbose=verbose)
print("Successfully installed schema version %d" % (version,))
-
+
else: # upgrade needed
error(
"Schema needs to be upgraded from %d to %d" %
Modified: CalendarServer/trunk/calendarserver/tools/calverify_diff.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/calverify_diff.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/calverify_diff.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -23,7 +23,7 @@
def analyze(fname):
-
+
lines = open(os.path.expanduser(fname)).read().splitlines()
total = len(lines)
ctr = 0
@@ -56,9 +56,11 @@
elif line.startswith("Attendee events mismatched in Organizer's calendar"):
ctr = _tableParser(ctr, "table4", parseTableMismatch)
ctr += 1
-
+
return results
+
+
def parseTableMissing(line):
splits = line.split("|")
organizer = splits[1].strip()
@@ -67,6 +69,8 @@
resid = splits[4].strip()
return (organizer, attendee, uid, resid,)
+
+
def parseTableMismatch(line):
splits = line.split("|")
organizer = splits[1].strip()
@@ -76,35 +80,41 @@
attendee_resid = splits[7].strip()
return (organizer, attendee, uid, organizer_resid, attendee_resid,)
+
+
def diff(results1, results2):
-
+
print("\n\nEvents missing from Attendee's calendars")
diffSets(results1["table1"], results2["table1"])
-
+
print("\n\nEvents mismatched between Organizer's and Attendee's calendars")
diffSets(results1["table2"], results2["table2"])
-
+
print("\n\nAttendee events missing in Organizer's calendar")
diffSets(results1["table3"], results2["table3"])
-
+
print("\n\nAttendee events mismatched in Organizer's calendar")
diffSets(results1["table4"], results2["table4"])
+
+
def diffSets(results1, results2):
-
+
s1 = set(results1)
s2 = set(results2)
-
+
d = s1 - s2
print("\nIn first, not in second: (%d)" % (len(d),))
for i in sorted(d):
print(i)
-
+
d = s2 - s1
print("\nIn second, not in first: (%d)" % (len(d),))
for i in sorted(d):
print(i)
+
+
def usage(error_msg=None):
if error_msg:
print(error_msg)
Modified: CalendarServer/trunk/calendarserver/tools/changeip_calendar.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/changeip_calendar.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/changeip_calendar.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -32,6 +32,7 @@
print(" new-hostname - new FQDN for the server")
+
def main():
name = os.path.basename(sys.argv[0])
@@ -93,6 +94,8 @@
if verbose:
print("Calendar Server: done")
+
+
def updatePlist(plist, oldIP, newIP, oldHostname, newHostname, verbose=False):
keys = (
@@ -118,13 +121,13 @@
key = keyPath[-1]
for step in path:
- if not parent.has_key(step):
+ if step not in parent:
parent = None
break
parent = parent[step]
if parent:
- if parent.has_key(key):
+ if key in parent:
value = parent[key]
if isinstance(value, list):
@@ -141,8 +144,5 @@
-
-
-
if __name__ == '__main__':
main()
Modified: CalendarServer/trunk/calendarserver/tools/config.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/config.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/config.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -94,6 +94,8 @@
else:
sys.exit(0)
+
+
def main():
try:
(optargs, args) = getopt(
@@ -140,6 +142,7 @@
processArgs(writable, args)
+
def processArgs(writable, args, restart=True):
"""
Perform the read/write operations requested in the command line args.
@@ -159,7 +162,7 @@
# This is an assignment
configKey, stringValue = configKey.split("=")
value = writable.convertToValue(stringValue)
- writable.set({configKey:value})
+ writable.set({configKey: value})
else:
# This is a read
c = config
@@ -208,6 +211,7 @@
"""
self.commands = commands
+
def validate(self):
"""
Validate all the commands by making sure this class implements
@@ -226,6 +230,7 @@
return False
return True
+
def run(self):
"""
Find the appropriate method for each command and call them.
@@ -243,6 +248,7 @@
respondWithError("Command failed: '%s'" % (str(e),))
raise
+
def command_readConfig(self, command):
"""
Return current configuration
@@ -261,6 +267,7 @@
setKeyPath(result, keyPath, value)
respond(command, result)
+
def command_writeConfig(self, command):
"""
Write config to secondary, writable plist
@@ -284,6 +291,7 @@
self.command_readConfig(command)
+
def setKeyPath(parent, keyPath, value):
"""
Allows the setting of arbitrary nested dictionary keys via a single
@@ -311,6 +319,8 @@
parent[parts[-1]] = value
return original
+
+
def getKeyPath(parent, keyPath):
"""
Allows the getting of arbitrary nested dictionary keys via a single
@@ -333,6 +343,8 @@
parent = child
return parent.get(parts[-1], None)
+
+
def flattenDictionary(dictionary, current=""):
"""
Returns a generator of (keyPath, value) tuples for the given dictionary,
@@ -353,6 +365,7 @@
yield (current + key, value)
+
def restartService(pidFilename):
"""
Given the path to a PID file, sends a HUP signal to the contained pid
@@ -375,6 +388,7 @@
pass
+
class WritableConfig(object):
"""
A wrapper around a Config object which allows writing of values. The idea
@@ -396,6 +410,7 @@
self.currentConfigSubset = ConfigDict()
self.dirty = False
+
def set(self, data):
"""
Merges data into a ConfigDict of changes intended to be saved to disk
@@ -409,6 +424,7 @@
mergeData(self.currentConfigSubset, data)
self.dirty = True
+
def read(self):
"""
Reads in the data contained in the writable plist file.
@@ -420,9 +436,11 @@
else:
self.currentConfigSubset = ConfigDict()
+
def toString(self):
return plistlib.writePlistToString(self.currentConfigSubset)
+
def save(self, restart=False):
"""
Writes any outstanding changes to the writable plist file. Optionally
@@ -437,6 +455,7 @@
if restart:
restartService(self.config.PIDFile)
+
@classmethod
def convertToValue(cls, string):
"""
@@ -461,8 +480,11 @@
return value
+
def respond(command, result):
sys.stdout.write(writePlistToString({'command' : command['command'], 'result' : result}))
+
+
def respondWithError(msg, status=1):
sys.stdout.write(writePlistToString({'error' : msg, }))
Modified: CalendarServer/trunk/calendarserver/tools/icalsplit.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/icalsplit.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/icalsplit.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -63,6 +63,7 @@
subcalendar_file.close()
+
def usage(e=None):
if e:
print(e)
@@ -85,6 +86,7 @@
sys.exit(0)
+
def main():
try:
(optargs, args) = getopt(
@@ -95,7 +97,7 @@
except GetoptError, e:
usage(e)
- for opt, arg in optargs:
+ for opt, _ignore_arg in optargs:
if opt in ("-h", "--help"):
usage()
Modified: CalendarServer/trunk/calendarserver/tools/managepostgres.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/managepostgres.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/managepostgres.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -26,15 +26,19 @@
print(s)
sys.exit(1)
+
+
def cmd(s):
print(s)
subprocess.call(s, shell=True)
+
+
def doInit(basedir):
-
+
cmd("mkdir %s/data" % (basedir,))
cmd("%s/bin/initdb -D %s/data" % (basedir, basedir,))
-
+
# Have the DB listen on all interfaces
with open("%s/data/postgresql.conf" % (basedir,)) as f:
conf = f.read()
@@ -42,7 +46,7 @@
conf = conf.replace("max_connections = 20 ", "max_connections = 500")
with open("%s/data/postgresql.conf" % (basedir,), "w") as f:
f.write(conf)
-
+
# Allow current user to auth to the DBs
with open("%s/data/pg_hba.conf" % (basedir,)) as f:
conf = f.read()
@@ -56,22 +60,32 @@
cmd("%s/bin/createdb augments" % (basedir,))
cmd("%s/bin/pg_ctl -D %s/data -l logfile stop" % (basedir, basedir,))
+
+
def doStart(basedir):
-
+
cmd("%s/bin/pg_ctl -D %s/data -l logfile start" % (basedir, basedir,))
+
+
def doStop(basedir):
-
+
cmd("%s/bin/pg_ctl -D %s/data -l logfile stop" % (basedir, basedir,))
+
+
def doRun(basedir, verbose):
-
- cmd("%s/bin/postgres %s -D %s/data" % (basedir, "-d 3" if verbose else "", basedir,))
+ cmd("%s/bin/postgres %s -D %s/data" % (basedir, "-d 3" if verbose else "", basedir,))
+
+
+
def doClean(basedir):
-
+
cmd("rm -rf %s/data" % (basedir,))
+
+
def main():
usage = "%prog [options] ACTION"
@@ -83,13 +97,13 @@
stop: stop postgres daemon
run: run postgres (non-daemon)
clean: remove databases
-
+
"""
description = "Tool to manage PostgreSQL"
version = "%prog v1.0"
parser = OptionParser(usage=usage, description=description, version=version)
parser.epilog = epilog
- parser.format_epilog = lambda _:epilog
+ parser.format_epilog = lambda _: epilog
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=True, help="Use debug logging for PostgreSQL")
Modified: CalendarServer/trunk/calendarserver/tools/migrate.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/migrate.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/migrate.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -54,6 +54,8 @@
else:
sys.exit(0)
+
+
def main():
try:
(optargs, args) = getopt(
@@ -67,7 +69,6 @@
configFileName = None
-
for opt, arg in optargs:
if opt in ("-h", "--help"):
usage()
Modified: CalendarServer/trunk/calendarserver/tools/notifications.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/notifications.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/notifications.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -71,6 +71,7 @@
sys.exit(0)
+
def main():
try:
(optargs, args) = getopt(
@@ -192,18 +193,21 @@
if sigint:
signal.signal(signal.SIGINT, self.sigint_handler)
+
@inlineCallbacks
def sigint_handler(self, num, frame):
print(" Shutting down...")
yield self.unsubscribeAll()
reactor.stop()
+
@inlineCallbacks
def unsubscribeAll(self):
if self.xmlStream is not None:
- for node, (url, name, kind) in self.nodes.iteritems():
+ for node, (_ignore_url, name, kind) in self.nodes.iteritems():
yield self.unsubscribe(node, name, kind)
+
def connected(self, xmlStream):
self.xmlStream = xmlStream
if self.verbose:
@@ -213,6 +217,7 @@
xmlStream.addObserver("/message/event/items",
self.handleMessageEventItems)
+
def disconnected(self, xmlStream):
self.xmlStream = None
if self.presenceCall is not None:
@@ -221,25 +226,29 @@
if self.verbose:
print("XMPP disconnected")
+
def initFailed(self, failure):
self.xmlStream = None
print("XMPP connection failure: %s" % (failure,))
reactor.stop()
+
@inlineCallbacks
def authenticated(self, xmlStream):
if self.verbose:
print("XMPP authentication successful")
self.sendPresence()
- for node, (url, name, kind) in self.nodes.iteritems():
+ for node, (_ignore_url, name, kind) in self.nodes.iteritems():
yield self.subscribe(node, name, kind)
print("Awaiting notifications (hit Control-C to end)")
+
def authFailed(self, e):
print("XMPP authentication failed")
reactor.stop()
+
def sendPresence(self):
if self.doKeepAlive and self.xmlStream is not None:
presence = domish.Element(('jabber:client', 'presence'))
@@ -247,6 +256,7 @@
self.presenceCall = reactor.callLater(self.presenceSeconds,
self.sendPresence)
+
def handleMessageEventItems(self, iq):
item = iq.firstChildElement().firstChildElement()
if item:
@@ -277,6 +287,7 @@
except Exception, e:
print("Subscription failure: %s %s" % (node, e))
+
@inlineCallbacks
def unsubscribe(self, node, name, kind):
iq = IQ(self.xmlStream)
@@ -310,14 +321,17 @@
def rawDataIn(self, buf):
print("RECV: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace'))
+
def rawDataOut(self, buf):
print("SEND: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace'))
+
class PropfindRequestor(AuthorizedHTTPGetter):
handleStatus_207 = lambda self: self.handleStatus_200
+
class PushMonitorService(Service):
"""
A service which uses CalDAV to determine which pubsub node(s) correspond
@@ -337,10 +351,11 @@
self.password = password
self.verbose = verbose
+
@inlineCallbacks
def startService(self):
try:
- subscribeNodes = { }
+ subscribeNodes = {}
if self.nodes is None:
paths = set()
principal = "/principals/users/%s/" % (self.username,)
@@ -379,6 +394,7 @@
print("Error:", e)
reactor.stop()
+
@inlineCallbacks
def getPrincipalDetails(self, path, includeCardDAV=True):
"""
@@ -443,8 +459,9 @@
print("Unable to look up principal details", e)
raise
- returnValue( (name, homes) )
+ returnValue((name, homes))
+
@inlineCallbacks
def getProxyFor(self):
"""
@@ -576,7 +593,7 @@
host = xmppServer
port = 5222
- if key and not nodes.has_key(key):
+ if key and key not in nodes:
nodes[key] = (href.text, name, kind)
except Exception, e:
@@ -593,7 +610,7 @@
if port is None:
raise Exception("Unable to determine xmpp server port")
- returnValue( (host, port, nodes) )
+ returnValue((host, port, nodes))
def startMonitoring(self, host, port, nodes):
Modified: CalendarServer/trunk/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/principals.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/principals.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -719,6 +719,7 @@
print("No auto-accept-group assigned to %s" % (prettyPrincipal(principal),))
+
@inlineCallbacks
def action_setValue(rootResource, directory, store, principal, name, value):
print("Setting %s to %s for %s" % (
@@ -735,6 +736,7 @@
))
+
def action_getValue(rootResource, directory, store, principal, name):
print("%s for %s is %s" % (
name,
@@ -743,6 +745,7 @@
))
+
def abort(msg, status=1):
sys.stdout.write("%s\n" % (msg,))
try:
Modified: CalendarServer/trunk/calendarserver/tools/resources.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/resources.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/resources.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -62,6 +62,8 @@
sys.exit(0)
+
+
def abort(msg, status=1):
sys.stdout.write("%s\n" % (msg,))
try:
@@ -70,9 +72,11 @@
pass
sys.exit(status)
+
+
def main():
try:
- (optargs, args) = getopt(
+ (optargs, _ignore_args) = getopt(
sys.argv[1:], "hf:v", [
"help",
"config=",
@@ -175,6 +179,7 @@
reactor.stop()
+
def queryForType(sourceService, recordType, verbose=False):
"""
Queries OD for all records of the specified record type
@@ -200,6 +205,7 @@
return results
+
@inlineCallbacks
def migrateResources(sourceService, destService, autoSchedules=None,
queryMethod=queryForType, verbose=False):
Modified: CalendarServer/trunk/calendarserver/tools/shell/cmd.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/shell/cmd.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/shell/cmd.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -772,7 +772,7 @@
class Handler(object):
- def addOutput(innerSelf, bytes, async=False):
+ def addOutput(innerSelf, bytes, async=False): #@NoSelf
"""
This is a delegate method, called by ManholeInterpreter.
"""
@@ -867,5 +867,5 @@
"""
self.terminal.write("Nothing happens.")
self.terminal.nextLine()
-
+
cmd_sql.hidden = ""
Modified: CalendarServer/trunk/calendarserver/tools/shell/terminal.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/shell/terminal.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/shell/terminal.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -72,6 +72,7 @@
sys.exit(0)
+
class ShellOptions(Options):
"""
Command line options for "calendarserver_shell".
@@ -181,6 +182,7 @@
self.activeCommand = None
self.emulate = "emacs"
+
def reloadCommands(self):
# FIXME: doesn't work for alternative Commands classes passed
# to __init__.
@@ -190,6 +192,7 @@
reload(calendarserver.tools.shell.cmd)
self.commands = calendarserver.tools.shell.cmd.Commands(self)
+
#
# Input handling
#
@@ -201,7 +204,7 @@
self.keyHandlers['\x04'] = self.handle_EOF # Control-D
self.keyHandlers['\x1c'] = self.handle_QUIT # Control-\
self.keyHandlers['\x0c'] = self.handle_FF # Control-L
- #self.keyHandlers['\t' ] = self.handle_TAB # Tab
+ #self.keyHandlers['\t' ] = self.handle_TAB # Tab
if self.emulate == "emacs":
# EMACS key bindinds
@@ -224,9 +227,11 @@
log.startLoggingWithObserver(observer)
+
def handle_INT(self):
return self.resetInputLine()
+
def handle_EOF(self):
if self.lineBuffer:
if self.emulate == "emacs":
@@ -236,6 +241,7 @@
else:
self.handle_QUIT()
+
def handle_FF(self):
"""
Handle a "form feed" byte - generally used to request a screen
@@ -244,12 +250,15 @@
# FIXME: Clear screen != redraw screen.
return self.clearScreen()
+
def handle_QUIT(self):
return self.exit()
+
def handle_TAB(self):
return self.completeLine()
+
#
# Utilities
#
@@ -262,6 +271,7 @@
self.terminal.cursorHome()
self.drawInputLine()
+
def resetInputLine(self):
"""
Reset the current input variables to their initial state.
@@ -272,6 +282,7 @@
self.terminal.nextLine()
self.drawInputLine()
+
@inlineCallbacks
def completeLine(self):
"""
@@ -318,6 +329,7 @@
self.terminal.write("%s%s\n" % (word, completion))
self.drawInputLine()
+
def exit(self):
"""
Exit.
@@ -325,6 +337,7 @@
self.terminal.loseConnection()
self.service.reactor.stop()
+
def handleFailure(self, f):
"""
Handle a failure raises in the interpreter by printing a
@@ -337,6 +350,7 @@
log.info(f.getTraceback())
self.resetInputLine()
+
#
# Command dispatch
#
@@ -386,6 +400,7 @@
else:
self.drawInputLine()
+
@staticmethod
def tokenize(line):
"""
@@ -405,6 +420,7 @@
return tokens
+
def main(argv=sys.argv, stderr=sys.stderr, reactor=None):
if reactor is None:
from twisted.internet import reactor
@@ -415,6 +431,7 @@
except UsageError, e:
usage(e)
+
def makeService(store):
from twistedcaldav.config import config
directory = getDirectory()
Modified: CalendarServer/trunk/calendarserver/tools/shell/test/test_cmd.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/shell/test/test_cmd.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/shell/test/test_cmd.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -15,7 +15,7 @@
# limitations under the License.
##
-import twisted.trial.unittest
+import twisted.trial.unittest
from twisted.internet.defer import inlineCallbacks
from txdav.common.icommondatastore import NotFoundError
@@ -29,6 +29,7 @@
self.protocol = ShellProtocol(None, commandsClass=CommandsBase)
self.commands = self.protocol.commands
+
@inlineCallbacks
def test_getTargetNone(self):
target = (yield self.commands.getTarget([], wdFallback=True))
@@ -37,21 +38,25 @@
target = (yield self.commands.getTarget([]))
self.assertEquals(target, None)
+
def test_getTargetMissing(self):
self.assertFailure(self.commands.getTarget(["/foo"]), NotFoundError)
+
@inlineCallbacks
def test_getTargetOne(self):
target = (yield self.commands.getTarget(["users"]))
match = (yield self.commands.wd.locate(["users"]))
self.assertEquals(target, match)
+
@inlineCallbacks
def test_getTargetSome(self):
target = (yield self.commands.getTarget(["users", "blah"]))
match = (yield self.commands.wd.locate(["users"]))
self.assertEquals(target, match)
+
def test_commandsNone(self):
allCommands = self.commands.commands()
self.assertEquals(sorted(allCommands), [])
@@ -59,6 +64,7 @@
allCommands = self.commands.commands(showHidden=True)
self.assertEquals(sorted(allCommands), [])
+
def test_commandsSome(self):
protocol = ShellProtocol(None, commandsClass=SomeCommands)
commands = protocol.commands
@@ -84,6 +90,7 @@
]
)
+
def test_complete(self):
items = (
"foo",
@@ -96,15 +103,16 @@
def c(word):
return sorted(CommandsBase.complete(word, items))
- self.assertEquals(c("" ), sorted(items))
- self.assertEquals(c("f" ), ["oo", "oobar"])
- self.assertEquals(c("foo" ), ["", "bar"])
- self.assertEquals(c("foobar" ), [""])
+ self.assertEquals(c(""), sorted(items))
+ self.assertEquals(c("f"), ["oo", "oobar"])
+ self.assertEquals(c("foo"), ["", "bar"])
+ self.assertEquals(c("foobar"), [""])
self.assertEquals(c("foobars"), [])
- self.assertEquals(c("baz" ), [""])
- self.assertEquals(c("q" ), ["uux"])
- self.assertEquals(c("xyzzy" ), [])
+ self.assertEquals(c("baz"), [""])
+ self.assertEquals(c("q"), ["uux"])
+ self.assertEquals(c("xyzzy"), [])
+
def test_completeCommands(self):
protocol = ShellProtocol(None, commandsClass=SomeCommands)
commands = protocol.commands
@@ -112,11 +120,12 @@
def c(word):
return sorted(commands.complete_commands(word))
- self.assertEquals(c("" ), ["a", "b"])
+ self.assertEquals(c(""), ["a", "b"])
self.assertEquals(c("a"), [""])
self.assertEquals(c("h"), ["idden"])
self.assertEquals(c("f"), [])
+
@inlineCallbacks
def _test_completeFiles(self, tests):
protocol = ShellProtocol(None, commandsClass=SomeCommands)
@@ -147,6 +156,7 @@
self.assertEquals((yield c(word)), completions, "Completing %r" % (word,))
self.assertEquals((yield d(word)), completions, "Completing %r" % (word,))
+
def test_completeFilesLevelOne(self):
return self._test_completeFiles((
(None , ["groups/", "locations/", "resources/", "uids/", "users/"]),
@@ -157,6 +167,7 @@
("groups", ["/"]),
))
+
def test_completeFilesLevelOneSlash(self):
return self._test_completeFiles((
("/" , ["groups/", "locations/", "resources/", "uids/", "users/"]),
@@ -166,6 +177,7 @@
("/groups", ["/"]),
))
+
def test_completeFilesDirectory(self):
return self._test_completeFiles((
("users/" , ["wsanchez", "admin"]), # FIXME: Look up users
@@ -181,11 +193,17 @@
test_completeFilesLevelTwo.todo = "Doesn't work yet"
+
class SomeCommands(CommandsBase):
def cmd_a(self, tokens):
pass
+
+
def cmd_b(self, tokens):
pass
+
+
def cmd_hidden(self, tokens):
pass
+
cmd_hidden.hidden = "Hidden"
Modified: CalendarServer/trunk/calendarserver/tools/shell/vfs.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/shell/vfs.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/shell/vfs.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -481,7 +481,7 @@
self._didInitChildren = True
- def _needsChildren(m):
+ def _needsChildren(m): #@NoSelf
def decorate(self, *args, **kwargs):
d = self._initChildren()
d.addCallback(lambda _: m(self, *args, **kwargs))
Modified: CalendarServer/trunk/calendarserver/tools/tables.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/tables.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/tables.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -31,28 +31,29 @@
class Table(object):
"""
Class that allows pretty printing ascii tables.
-
+
The table supports multiline headers and footers, independent
- column formatting by row, alternative tab-delimited output.
+ column formatting by row, alternative tab-delimited output.
"""
-
+
class ColumnFormat(object):
"""
Defines the format string, justification and span for a column.
"""
-
+
LEFT_JUSTIFY = 0
RIGHT_JUSTIFY = 1
CENTER_JUSTIFY = 2
def __init__(self, strFormat="%s", justify=LEFT_JUSTIFY, span=1):
-
+
self.format = strFormat
self.justify = justify
self.span = span
+
def __init__(self, table=None):
-
+
self.headers = []
self.headerColumnFormats = []
self.rows = []
@@ -65,71 +66,83 @@
if table:
self.setData(table)
+
def setData(self, table):
-
+
self.hasTitles = True
self.headers.append(table[0])
self.rows = table[1:]
self._getMaxColumnCount()
+
def setDefaultColumnFormats(self, columnFormats):
-
+
self.defaultColumnFormats = columnFormats
+
def addDefaultColumnFormat(self, columnFormat):
-
+
self.defaultColumnFormats.append(columnFormat)
+
def setHeaders(self, rows, columnFormats=None):
-
+
self.headers = rows
- self.headerColumnFormats = columnFormats if columnFormats else [None,] * len(self.headers)
+ self.headerColumnFormats = columnFormats if columnFormats else [None, ] * len(self.headers)
self._getMaxColumnCount()
+
def addHeader(self, row, columnFormats=None):
-
+
self.headers.append(row)
self.headerColumnFormats.append(columnFormats)
self._getMaxColumnCount()
+
def addHeaderDivider(self, skipColumns=()):
-
+
self.headers.append((None, skipColumns,))
self.headerColumnFormats.append(None)
+
def setFooters(self, row, columnFormats=None):
-
+
self.footers = row
- self.footerColumnFormats = columnFormats if columnFormats else [None,] * len(self.footers)
+ self.footerColumnFormats = columnFormats if columnFormats else [None, ] * len(self.footers)
self._getMaxColumnCount()
+
def addFooter(self, row, columnFormats=None):
-
+
self.footers.append(row)
self.footerColumnFormats.append(columnFormats)
self._getMaxColumnCount()
+
def addRow(self, row=None, columnFormats=None):
-
+
self.rows.append(row)
if columnFormats:
self.columnFormatsByRow[len(self.rows) - 1] = columnFormats
self._getMaxColumnCount()
-
+
+
def addDivider(self, skipColumns=()):
-
+
self.rows.append((None, skipColumns,))
+
def toString(self):
output = StringIO()
self.printTable(os=output)
return output.getvalue()
+
def printTable(self, os=stdout):
-
+
maxWidths = self._getMaxWidths()
-
+
self.printDivider(os, maxWidths, False)
if self.headers:
for header, format in zip(self.headers, self.headerColumnFormats):
@@ -142,9 +155,10 @@
for footer, format in zip(self.footers, self.footerColumnFormats):
self.printRow(os, footer, self._getFooterColumnFormat(format), maxWidths)
self.printDivider(os, maxWidths, False)
-
+
+
def printRow(self, os, row, format, maxWidths):
-
+
if row is None or type(row) is tuple and row[0] is None:
self.printDivider(os, maxWidths, skipColumns=row[1] if type(row) is tuple else ())
else:
@@ -165,8 +179,8 @@
t += " " + text + " |"
t += "\n"
os.write(t)
-
+
def printDivider(self, os, maxWidths, intermediate=True, double=False, skipColumns=()):
t = "|" if intermediate else "+"
for widthctr, width in enumerate(maxWidths):
@@ -179,8 +193,9 @@
t += "\n"
os.write(t)
+
def printTabDelimitedData(self, os=stdout, footer=True):
-
+
if self.headers:
titles = [""] * len(self.headers[0])
for row, header in enumerate(self.headers):
@@ -193,20 +208,22 @@
for footer in self.footers:
self.printTabDelimitedRow(os, footer, self._getFooterColumnFormat(self.footerColumnFormats[0]))
+
def printTabDelimitedRow(self, os, row, format):
-
+
if row is None:
row = [""] * self.columnCount
-
+
if len(row) != self.columnCount:
row = list(row)
row.extend([""] * (self.columnCount - len(row)))
textItems = [self._columnText(row, ctr, format) for ctr in xrange((len(row)))]
os.write("\t".join(textItems) + "\n")
-
+
+
def _getMaxColumnCount(self):
-
+
self.columnCount = 0
if self.headers:
for header in self.headers:
@@ -217,6 +234,7 @@
for footer in self.footers:
self.columnCount = max(self.columnCount, len(footer) if footer else 0)
+
def _getMaxWidths(self):
maxWidths = [0] * self.columnCount
@@ -224,55 +242,60 @@
if self.headers:
for header, format in zip(self.headers, self.headerColumnFormats):
self._updateMaxWidthsFromRow(header, self._getHeaderColumnFormat(format), maxWidths)
-
+
for ctr, row in enumerate(self.rows):
self._updateMaxWidthsFromRow(row, self._getColumnFormatForRow(ctr), maxWidths)
if self.footers:
for footer, format in zip(self.footers, self.footerColumnFormats):
self._updateMaxWidthsFromRow(footer, self._getFooterColumnFormat(format), maxWidths)
-
+
return maxWidths
+
def _updateMaxWidthsFromRow(self, row, format, maxWidths):
-
+
if row and (type(row) is not tuple or row[0] is not None):
ctr = 0
while ctr < len(row):
-
- text = self._columnText(row, ctr, format)
+
+ text = self._columnText(row, ctr, format)
startCtr = ctr
for _ignore_span in xrange(format[startCtr].span if format else 1):
maxWidths[ctr] = max(maxWidths[ctr], len(text) / (format[startCtr].span if format else 1))
ctr += 1
-
+
+
def _getHeaderColumnFormat(self, format):
-
+
if format:
return format
else:
justify = Table.ColumnFormat.CENTER_JUSTIFY if len(self.headers) == 1 else Table.ColumnFormat.LEFT_JUSTIFY
- return [Table.ColumnFormat(justify = justify)] * self.columnCount
+ return [Table.ColumnFormat(justify=justify)] * self.columnCount
+
def _getFooterColumnFormat(self, format):
-
+
if format:
return format
else:
return self.defaultColumnFormats
+
def _getColumnFormatForRow(self, ctr):
-
+
if ctr in self.columnFormatsByRow:
return self.columnFormatsByRow[ctr]
else:
return self.defaultColumnFormats
+
def _columnText(self, row, column, format, width=0):
-
+
if row is None or column >= len(row):
return ""
-
+
colData = row[column]
if colData is None:
colData = ""
Modified: CalendarServer/trunk/calendarserver/tools/test/test_agent.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_agent.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/test/test_agent.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -22,7 +22,7 @@
from twistedcaldav.test.util import TestCase
from twisted.internet.defer import inlineCallbacks
from twisted.internet.task import Clock
- from twisted.cred.error import UnauthorizedLogin
+ from twisted.cred.error import UnauthorizedLogin
from twisted.web.resource import IResource
from twisted.web.resource import ForbiddenResource
RUN_TESTS = True
@@ -31,7 +31,6 @@
-
if RUN_TESTS:
class AgentTestCase(TestCase):
@@ -67,7 +66,6 @@
else:
self.fail("Didn't raise UnauthorizedLogin")
-
# Record exists, but invalid credentials
fakeOpenDirectory.returnThisRecord("fooRecord")
fakeOpenDirectory.returnThisAuthResponse(False)
@@ -78,14 +76,12 @@
else:
self.fail("Didn't raise UnauthorizedLogin")
-
# Record exists, valid credentials
fakeOpenDirectory.returnThisRecord("fooRecord")
fakeOpenDirectory.returnThisAuthResponse(True)
avatar = (yield c.requestAvatarId(creds))
self.assertEquals(avatar, "foo")
-
# Record exists, but missing fields in credentials
del creds.fields["nonce"]
fakeOpenDirectory.returnThisRecord("fooRecord")
@@ -102,11 +98,11 @@
realm = AgentRealm("root", ["abc"])
# Valid avatar
- interface, resource, ignored = realm.requestAvatar("abc", None, IResource)
+ _ignore_interface, resource, ignored = realm.requestAvatar("abc", None, IResource)
self.assertEquals(resource, "root")
# Not allowed avatar
- interface, resource, ignored = realm.requestAvatar("def", None, IResource)
+ _ignore_interface, resource, ignored = realm.requestAvatar("def", None, IResource)
self.assertTrue(isinstance(resource, ForbiddenResource))
# Interface unhandled
@@ -118,7 +114,6 @@
self.fail("Didn't raise NotImplementedError")
-
class InactivityDectectorTestCase(TestCase):
def test_inactivity(self):
@@ -156,7 +151,6 @@
return "127.0.0.1"
-
class FakeOpenDirectory(object):
def returnThisRecord(self, response):
@@ -175,7 +169,6 @@
ODNSerror = "Error"
-
class FakeCredentials(object):
def __init__(self, username, fields):
Modified: CalendarServer/trunk/calendarserver/tools/test/test_config.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_config.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/test/test_config.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -110,6 +110,7 @@
self.assertEquals(writable2.currentConfigSubset, {'key1': u'\U0001f4a3'})
+
class ConfigTestCase(RunCommandTestCase):
@inlineCallbacks
Modified: CalendarServer/trunk/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_gateway.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/test/test_gateway.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -187,7 +187,7 @@
self.assertEquals(results["result"]["RealName"], u'Updated Address')
self.assertEquals(results["result"]["StreetAddress"], u'Updated Street Address')
self.assertEquals(results["result"]["Geo"], u'Updated Geo')
-
+
results = yield self.runCommand(command_deleteAddress)
results = yield self.runCommand(command_getAddressList)
@@ -333,6 +333,7 @@
results = yield self.runCommand(command_purgeOldEventsNoDays)
self.assertEquals(results["result"]["RetainDays"], 365)
+
@inlineCallbacks
def test_readConfig(self):
"""
Modified: CalendarServer/trunk/calendarserver/tools/test/test_resources.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_resources.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/test/test_resources.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -74,7 +74,7 @@
@classmethod
def getAugmentRecord(cls, guid, recordType):
- if not cls.records.has_key(guid):
+ if guid not in cls.records:
record = StubAugmentRecord(guid=guid)
cls.records[guid] = record
return succeed(cls.records[guid])
@@ -128,11 +128,9 @@
self.assertTrue(guid in StubAugmentService.records)
-
#
# Add more to OD and re-migrate
#
-
data[dsattributes.kDSStdRecordTypeResources].append(
['projector3', {
strGUID : '9C99E240-E915-4012-82FA-99E0F638D7EF',
Modified: CalendarServer/trunk/calendarserver/tools/test/test_util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/test_util.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/tools/test/test_util.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -29,6 +29,7 @@
self.assertEquals(config.EnableCalDAV, True)
self.assertEquals(config.EnableCardDAV, True)
+
def test_checkDirectory(self):
tmpDir = tempfile.mkdtemp()
tmpFile = os.path.join(tmpDir, "tmpFile")
Modified: CalendarServer/trunk/calendarserver/webcal/resource.py
===================================================================
--- CalendarServer/trunk/calendarserver/webcal/resource.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/webcal/resource.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -59,36 +59,44 @@
),
)
+
def etag(self):
# Can't be calculated here
return succeed(None)
+
def contentLength(self):
# Can't be calculated here
return None
+
def lastModified(self):
return None
+
def exists(self):
return True
+
def displayName(self):
return "Web Calendar"
+
def contentType(self):
return MimeType.fromString("text/html; charset=utf-8")
+
def contentEncoding(self):
return None
+
def createSimilarFile(self, path):
return DAVFile(path, principalCollections=self.principalCollections())
- _htmlContent_lastCheck = 0
- _htmlContent_statInfo = 0
+ _htmlContent_lastCheck = 0
+ _htmlContent_statInfo = 0
_htmlContentDebug_lastCheck = 0
- _htmlContentDebug_statInfo = 0
+ _htmlContentDebug_statInfo = 0
def htmlContent(self, debug=False):
if debug:
@@ -134,6 +142,7 @@
return getattr(self, cacheAttr)
+
def render(self, request):
if not self.fp.isdir():
return responsecode.NOT_FOUND
@@ -202,6 +211,7 @@
return ""
+
def getLocalTimezone():
"""
Returns the default timezone for the server. The order of precedence is:
Modified: CalendarServer/trunk/calendarserver/webcal/test/test_resource.py
===================================================================
--- CalendarServer/trunk/calendarserver/webcal/test/test_resource.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/calendarserver/webcal/test/test_resource.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -26,9 +26,11 @@
def stubLookup(self):
return self._storedLookup
+
def stubHasTZ(self, ignored):
return self._storedHasTZ.pop()
+
def setUp(self):
self.patch(
calendarserver.webcal.resource, "lookupSystemTimezone",
@@ -38,6 +40,7 @@
calendarserver.webcal.resource, "hasTZ", self.stubHasTZ
)
+
def test_getLocalTimezone(self):
# Empty config, system timezone known = use system timezone
Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -121,7 +121,7 @@
self.restrictToGUID = True
self.restrictedTimestamp = 0
- # Set up the /Local/Default node if it's in the search path so we can
+ # Set up the /Local/Default node if it's in the search path so we can
# send custom queries to it
self.localNode = None
try:
@@ -581,7 +581,7 @@
def collectResults(results):
self.log.debug("Got back %d records from OD" % (len(results),))
- for key, value in results:
+ for _ignore_key, value in results:
# self.log.debug("OD result: {key} {value}", key=key, value=value)
try:
recordNodeName = value.get(
@@ -787,7 +787,7 @@
def collectResults(results):
self.log.debug("Got back %d records from OD" % (len(results),))
- for key, value in results:
+ for _ignore_key, value in results:
# self.log.debug("OD result: {key} {value}", key=key, value=value)
try:
recordNodeName = value.get(
@@ -1375,12 +1375,13 @@
return results
+
def buildNestedQueryFromTokens(tokens, mapping):
"""
Build a DS query espression such that all the tokens must appear in either
the fullName (anywhere), emailAddresses (at the beginning) or record name
(at the beginning).
-
+
@param tokens: The tokens to search on
@type tokens: C{list} of C{str}
@param mapping: The mapping of DirectoryRecord attributes to OD attributes
@@ -1409,6 +1410,7 @@
return dsquery.expression(dsquery.expression.AND, outer)
+
class OpenDirectoryRecord(CachingDirectoryRecord):
"""
OpenDirectory implementation of L{IDirectoryRecord}.
Modified: CalendarServer/trunk/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendar.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/calendar.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -36,11 +36,11 @@
from twistedcaldav.config import config
from twistedcaldav.directory.idirectory import IDirectoryService
-from twistedcaldav.directory.common import uidsResourceName,\
+from twistedcaldav.directory.common import uidsResourceName, \
CommonUIDProvisioningResource, CommonHomeTypeProvisioningResource
from twistedcaldav.directory.wiki import getWikiACL
-from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
+from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource, \
DAVResourceWithChildrenMixin
from twistedcaldav.resource import CalendarHomeResource
@@ -56,6 +56,8 @@
+ config.CalDAVComplianceClasses
)
+
+
class DirectoryCalendarProvisioningResource (
ReadOnlyResourceMixIn,
CalDAVComplianceMixIn,
@@ -65,15 +67,19 @@
def defaultAccessControlList(self):
return config.ProvisioningResourceACL
+
def etag(self):
return succeed(ETag(str(uuid4())))
+
def contentType(self):
return MimeType("httpd", "unix-directory")
+
+
class DirectoryCalendarHomeProvisioningResource (DirectoryCalendarProvisioningResource):
"""
- Resource which provisions calendar home collections as needed.
+ Resource which provisions calendar home collections as needed.
"""
def __init__(self, directory, url, store):
"""
@@ -100,22 +106,27 @@
self.putChild(uidsResourceName, DirectoryCalendarHomeUIDProvisioningResource(self))
+
def url(self):
return self._url
+
def listChildren(self):
return self.directory.recordTypes()
+
def principalCollections(self):
# FIXME: directory.principalCollection smells like a hack
# See DirectoryPrincipalProvisioningResource.__init__()
return self.directory.principalCollection.principalCollections()
+
def principalForRecord(self, record):
# FIXME: directory.principalCollection smells like a hack
# See DirectoryPrincipalProvisioningResource.__init__()
return self.directory.principalCollection.principalForRecord(record)
+
def homeForDirectoryRecord(self, record, request):
uidResource = self.getChild(uidsResourceName)
if uidResource is None:
@@ -123,16 +134,20 @@
else:
return uidResource.homeResourceForRecord(record, request)
+
##
# DAV
##
-
+
def isCollection(self):
return True
+
def displayName(self):
return "calendars"
+
+
class DirectoryCalendarHomeTypeProvisioningResource(
CommonHomeTypeProvisioningResource,
DirectoryCalendarProvisioningResource
@@ -155,6 +170,7 @@
self.recordType = recordType
self._parent = parent
+
def url(self):
return joinURL(self._parent.url(), self.recordType)
@@ -173,19 +189,23 @@
# Not a listable collection
raise HTTPError(responsecode.FORBIDDEN)
+
def makeChild(self, name):
return None
+
##
# DAV
##
-
+
def isCollection(self):
return True
+
def displayName(self):
return self.recordType
+
##
# ACL
##
@@ -193,9 +213,12 @@
def principalCollections(self):
return self._parent.principalCollections()
+
def principalForRecord(self, record):
return self._parent.principalForRecord(record)
+
+
class DirectoryCalendarHomeUIDProvisioningResource (
CommonUIDProvisioningResource,
DirectoryCalendarProvisioningResource
@@ -241,5 +264,6 @@
d.addCallback(gotACL)
return d
+
def principalForRecord(self):
return self.parent.principalForRecord(self.record)
Modified: CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -49,9 +49,9 @@
from twistedcaldav.directory.util import normalizeUUID
from twistedcaldav.config import config, fullServerPath
-from twistedcaldav.database import AbstractADBAPIDatabase, ADBAPISqliteMixin,\
+from twistedcaldav.database import AbstractADBAPIDatabase, ADBAPISqliteMixin, \
ADBAPIPostgreSQLMixin
-from twistedcaldav.extensions import DAVPrincipalResource,\
+from twistedcaldav.extensions import DAVPrincipalResource, \
DAVResourceWithChildrenMixin
from twistedcaldav.extensions import ReadOnlyWritePropertiesResourceMixIn
from twistedcaldav.memcacher import Memcacher
@@ -177,16 +177,16 @@
super(CalendarUserProxyPrincipalResource, self).__init__()
DAVResourceWithChildrenMixin.__init__(self)
- self.parent = parent
- self.proxyType = proxyType
- self._url = url
+ self.parent = parent
+ self.proxyType = proxyType
+ self._url = url
# FIXME: if this is supposed to be public, it needs a better name:
- self.pcollection = self.parent.parent.parent
+ self.pcollection = self.parent.parent.parent
# Principal UID is parent's GUID plus the proxy type; this we can easily
# map back to a principal.
- self.uid = "%s#%s" % (self.parent.principalUID(), proxyType)
+ self.uid = "%s#%s" % (self.parent.principalUID(), proxyType)
self._alternate_urls = tuple(
joinURL(url, proxyType) + slash
for url in parent.alternateURIs()
@@ -206,6 +206,7 @@
"""
return ProxyDBService
+
def resourceType(self):
if self.proxyType == "calendar-proxy-read":
return davxml.ResourceType.calendarproxyread #@UndefinedVariable
@@ -214,6 +215,7 @@
else:
return super(CalendarUserProxyPrincipalResource, self).resourceType()
+
def isProxyType(self, read_write):
if (
read_write and self.proxyType == "calendar-proxy-write" or
@@ -223,12 +225,15 @@
else:
return False
+
def isCollection(self):
return True
+
def etag(self):
return succeed(None)
+
def deadProperties(self):
if not hasattr(self, "_dead_properties"):
self._dead_properties = NonePropertyStore(self)
@@ -302,6 +307,7 @@
[p.principalUID() for p in principals],
)
+
##
# HTTP
##
@@ -329,15 +335,19 @@
# FIXME: Add API to IDirectoryRecord for getting a record URI?
return self._alternate_urls
+
def principalURL(self):
return self._url
+
def principalUID(self):
return self.uid
+
def principalCollections(self):
return self.parent.principalCollections()
+
@inlineCallbacks
def _expandMemberUIDs(self, uid=None, relatives=None, uids=None, infinity=False):
if uid is None:
@@ -367,6 +377,7 @@
returnValue(relatives)
+
@inlineCallbacks
def _directGroupMembers(self):
# Get member UIDs from database and map to principal resources
@@ -377,7 +388,7 @@
if p:
# Only principals enabledForLogin can be a delegate
# (and groups as well)
- if (p.record.enabledForLogin or
+ if (p.record.enabledForLogin or
p.record.recordType == p.record.service.recordType_groups):
found.append(p)
# Make sure any outstanding deletion timer entries for
@@ -388,9 +399,11 @@
returnValue(found)
+
def groupMembers(self):
return self._expandMemberUIDs()
+
@inlineCallbacks
def expandedGroupMembers(self):
"""
@@ -399,6 +412,7 @@
"""
returnValue((yield self._expandMemberUIDs(infinity=True)))
+
def groupMemberships(self):
# Get membership UIDs and map to principal resources
d = self._index().getMemberships(self.uid)
@@ -409,6 +423,7 @@
])
return d
+
@inlineCallbacks
def containsPrincipal(self, principal):
"""
@@ -427,6 +442,8 @@
returnValue(True)
returnValue(False)
+
+
class ProxyDB(AbstractADBAPIDatabase):
"""
A database to maintain calendar user proxy group memberships.
@@ -440,7 +457,7 @@
log = Logger()
schema_version = "4"
- schema_type = "CALENDARUSERPROXY"
+ schema_type = "CALENDARUSERPROXY"
class ProxyDBMemcacher(Memcacher):
@@ -484,7 +501,7 @@
return self.delete("memberships:%s" % (str(guid),))
def setDeletionTimer(self, guid, delay):
- return self.set("del:%s" % (str(guid),), str(self.getTime()+delay))
+ return self.set("del:%s" % (str(guid),), str(self.getTime() + delay))
def checkDeletionTimer(self, guid):
# True means it's overdue, False means it's not, None means no timer
@@ -510,11 +527,13 @@
theTime = int(time.time())
return theTime
+
def __init__(self, dbID, dbapiName, dbapiArgs, **kwargs):
AbstractADBAPIDatabase.__init__(self, dbID, dbapiName, dbapiArgs, True, **kwargs)
-
+
self._memcacher = ProxyDB.ProxyDBMemcacher("ProxyDB")
+
@inlineCallbacks
def setGroupMembers(self, principalUID, members):
"""
@@ -542,6 +561,7 @@
yield self._memcacher.deleteMembership(member)
yield self._memcacher.deleteMember(principalUID)
+
@inlineCallbacks
def setGroupMembersInDatabase(self, principalUID, members):
"""
@@ -553,7 +573,8 @@
# Remove what is there, then add it back.
yield self._delete_from_db(principalUID)
yield self._add_to_db(principalUID, members)
-
+
+
@inlineCallbacks
def changeGroupMembersInDatabase(self, principalUID, addMembers, removeMembers):
"""
@@ -568,7 +589,8 @@
yield self._delete_from_db_one(principalUID, member)
for member in addMembers:
yield self._add_to_db_one(principalUID, member)
-
+
+
@inlineCallbacks
def removeGroup(self, principalUID):
"""
@@ -581,13 +603,14 @@
members = yield self.getMembers(principalUID)
yield self._delete_from_db(principalUID)
-
+
# Update cache
if members:
for member in members:
yield self._memcacher.deleteMembership(member)
yield self._memcacher.deleteMember(principalUID)
+
@inlineCallbacks
def removePrincipal(self, principalUID, delay=None):
"""
@@ -596,7 +619,7 @@
@param principalUID: the UID of the principal to remove.
"""
# FIXME: This method doesn't appear to be used anywhere. Still needed?
-
+
if delay:
# We are going to remove the principal only after <delay> seconds
# has passed since we first chose to remove it, to protect against
@@ -640,6 +663,7 @@
yield self._memcacher.deleteMembership(principalUID)
yield self._memcacher.clearDeletionTimer(principalUID)
+
def refreshPrincipal(self, principalUID):
"""
Bring back to life a principal that was previously deleted.
@@ -647,9 +671,10 @@
@param principalUID:
@type principalUID:
"""
-
+
return self._memcacher.clearDeletionTimer(principalUID)
+
def getMembers(self, principalUID):
"""
Return the list of group member UIDs for the specified principal.
@@ -667,7 +692,7 @@
d.addCallback(lambda _: members)
return d
- d = self.query("select MEMBER from GROUPS where GROUPNAME = :1", (principalUID.decode("utf-8"),))
+ d = self.query("select MEMBER from GROUPS where GROUPNAME = :1", (principalUID.decode("utf-8"),))
d.addCallback(gotMembersFromDB)
return d
@@ -675,10 +700,11 @@
d.addCallback(gotCachedMembers)
return d
+
def getMemberships(self, principalUID):
"""
Return the list of group principal UIDs the specified principal is a member of.
-
+
@return: a deferred returning a C{set} of memberships.
"""
def gotCachedMemberships(memberships):
@@ -692,7 +718,7 @@
d.addCallback(lambda _: memberships)
return d
- d = self.query("select GROUPNAME from GROUPS where MEMBER = :1", (principalUID.decode("utf-8"),))
+ d = self.query("select GROUPNAME from GROUPS where MEMBER = :1", (principalUID.decode("utf-8"),))
d.addCallback(gotMembershipsFromDB)
return d
@@ -700,6 +726,7 @@
d.addCallback(gotCachedMemberships)
return d
+
@inlineCallbacks
def _add_to_db(self, principalUID, members):
"""
@@ -716,6 +743,7 @@
""", (principalUID.decode("utf-8"), member,)
)
+
def _add_to_db_one(self, principalUID, memberUID):
"""
Insert the specified entry into the database.
@@ -730,6 +758,7 @@
""", (principalUID.decode("utf-8"), memberUID.decode("utf-8"),)
)
+
def _delete_from_db(self, principalUID):
"""
Deletes the specified entry from the database.
@@ -738,6 +767,7 @@
"""
return self.execute("delete from GROUPS where GROUPNAME = :1", (principalUID.decode("utf-8"),))
+
def _delete_from_db_one(self, principalUID, memberUID):
"""
Deletes the specified entry from the database.
@@ -747,6 +777,7 @@
"""
return self.execute("delete from GROUPS where GROUPNAME = :1 and MEMBER = :2", (principalUID.decode("utf-8"), memberUID.decode("utf-8"),))
+
def _delete_from_db_member(self, principalUID):
"""
Deletes the specified member entry from the database.
@@ -755,18 +786,21 @@
"""
return self.execute("delete from GROUPS where MEMBER = :1", (principalUID.decode("utf-8"),))
+
def _db_version(self):
"""
@return: the schema version assigned to this index.
"""
return ProxyDB.schema_version
+
def _db_type(self):
"""
@return: the collection type assigned to this index.
"""
return ProxyDB.schema_type
+
@inlineCallbacks
def _db_init_data_tables(self):
"""
@@ -781,7 +815,7 @@
"GROUPS",
(
("GROUPNAME", "text"),
- ("MEMBER", "text"),
+ ("MEMBER", "text"),
),
ifnotexists=True,
)
@@ -877,17 +911,19 @@
#
return self._db_execute("delete from GROUPS")
+
@inlineCallbacks
def clean(self):
-
+
if not self.initialized:
yield self.open()
for group in [row[0] for row in (yield self.query("select GROUPNAME from GROUPS"))]:
self.removeGroup(group)
-
+
yield super(ProxyDB, self).clean()
+
@inlineCallbacks
def getAllMembers(self):
"""
@@ -908,6 +944,8 @@
ADBAPISqliteMixin.__init__(self)
ProxyDB.__init__(self, "Proxies", "sqlite3", (fullServerPath(config.DataRoot, dbpath),))
+
+
class ProxyPostgreSQLDB(ADBAPIPostgreSQLMixin, ProxyDB):
"""
PostgreSQL based augment database implementation.
@@ -915,7 +953,7 @@
def __init__(self, host, database, user=None, password=None, dbtype=None):
- ADBAPIPostgreSQLMixin.__init__(self, )
+ ADBAPIPostgreSQLMixin.__init__(self,)
ProxyDB.__init__(self, "Proxies", "pgdb", (), host=host, database=database, user=user, password=password,)
if dbtype:
ProxyDB.schema_type = dbtype
Modified: CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -34,15 +34,15 @@
log = Logger()
-ELEMENT_PROXIES = "proxies"
-ELEMENT_RECORD = "record"
+ELEMENT_PROXIES = "proxies"
+ELEMENT_RECORD = "record"
-ELEMENT_GUID = "guid"
-ELEMENT_PROXIES = "proxies"
+ELEMENT_GUID = "guid"
+ELEMENT_PROXIES = "proxies"
ELEMENT_READ_ONLY_PROXIES = "read-only-proxies"
-ELEMENT_MEMBER = "member"
+ELEMENT_MEMBER = "member"
-ATTRIBUTE_REPEAT = "repeat"
+ATTRIBUTE_REPEAT = "repeat"
class XMLCalendarUserProxyLoader(object):
"""
@@ -51,6 +51,7 @@
def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.xmlFile)
+
def __init__(self, xmlFile):
self.items = []
@@ -65,13 +66,14 @@
# FIXME: RuntimeError is dumb.
self._parseXML(proxies_node)
+
def _parseXML(self, rootnode):
"""
Parse the XML root node from the augments configuration document.
@param rootnode: the L{Element} to parse.
"""
for child in rootnode:
-
+
if child.tag != ELEMENT_RECORD:
raise RuntimeError("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, self.xmlFile,))
@@ -81,7 +83,7 @@
write_proxies = set()
read_proxies = set()
for node in child:
-
+
if node.tag == ELEMENT_GUID:
guid = node.text
@@ -92,40 +94,43 @@
self._parseMembers(node, write_proxies if node.tag == ELEMENT_PROXIES else read_proxies)
else:
raise RuntimeError("Invalid element '%s' in proxies file: '%s'" % (node.tag, self.xmlFile,))
-
+
# Must have at least a guid
if not guid:
raise RuntimeError("Invalid record '%s' without a guid in proxies file: '%s'" % (child, self.xmlFile,))
-
+
if repeat > 1:
- for i in xrange(1, repeat+1):
+ for i in xrange(1, repeat + 1):
self._buildRecord(guid, write_proxies, read_proxies, i)
else:
self._buildRecord(guid, write_proxies, read_proxies)
+
def _parseMembers(self, node, addto):
for child in node:
if child.tag == ELEMENT_MEMBER:
addto.add(child.text)
-
+
+
def _buildRecord(self, guid, write_proxies, read_proxies, count=None):
def expandCount(value, count):
-
+
if type(value) in types.StringTypes:
return value % (count,) if count and "%" in value else value
else:
return value
-
+
guid = expandCount(guid, count)
write_proxies = set([expandCount(member, count) for member in write_proxies])
read_proxies = set([expandCount(member, count) for member in read_proxies])
-
+
self.items.append((guid, write_proxies, read_proxies,))
+
@inlineCallbacks
def updateProxyDB(self):
-
+
db = calendaruserproxy.ProxyDBService
for item in self.items:
guid, write_proxies, read_proxies = item
Modified: CalendarServer/trunk/twistedcaldav/directory/digest.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/digest.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/digest.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -57,6 +57,7 @@
"""
pass
+
def set(self, key, value):
"""
Store per-client credential information the first time a nonce is generated and used.
@@ -68,6 +69,7 @@
"""
pass
+
def get(self, key):
"""
Validate client supplied credentials by comparing with the cached values. If valid, store the new
@@ -80,6 +82,7 @@
"""
pass
+
def delete(self, key):
"""
Remove the record associated with the supplied key.
@@ -89,6 +92,8 @@
"""
pass
+
+
class DigestCredentialsMemcache(Memcacher):
implements(IDigestCredentialsDatabase)
@@ -101,14 +106,16 @@
pickle=True,
)
+
def has_key(self, key):
"""
See IDigestCredentialsDatabase.
"""
d = self.get(key)
- d.addCallback(lambda value:value is not None)
+ d.addCallback(lambda value: value is not None)
return d
+
def set(self, key, value):
"""
See IDigestCredentialsDatabase.
@@ -119,6 +126,8 @@
expireTime=self.CHALLENGE_MAXTIME_SECS
)
+
+
class QopDigestCredentialFactory(DigestCredentialFactory):
"""
See txweb2.auth.digest.DigestCredentialFactory
@@ -163,7 +172,7 @@
c = challenge['nonce']
# Make sure it is not a duplicate
- result = (yield self.db.has_key(c))
+ result = (yield self.db.has_key(c)) #@IgnorePep8
if result:
raise AssertionError("nonce value already cached in credentials database: %s" % (c,))
@@ -237,13 +246,14 @@
self._real.authenticationRealm,
auth)
- if not self.qop and credentials.fields.has_key('qop'):
+ if not self.qop and 'qop' in credentials.fields:
del credentials.fields['qop']
returnValue(credentials)
else:
raise error.LoginFailed('Invalid nonce/cnonce values')
+
@inlineCallbacks
def _validate(self, auth, request):
"""
@@ -303,6 +313,7 @@
returnValue(True)
+
def _invalidate(self, nonce):
"""
Invalidate cached credentials for the specified nonce value.
Modified: CalendarServer/trunk/twistedcaldav/directory/internal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/internal.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/internal.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -45,20 +45,22 @@
def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.realmName)
+
def __init__(self, realm):
super(InternalDirectoryService, self).__init__()
self.realmName = realm
self._records()
+
def _records(self):
"""
Build the list of records.
-
+
Right now we want public/global and public/directory for
global and directory address books.
"""
-
+
if not hasattr(self, "_cachedRecords"):
self._cachedRecords = (
InternalDirectoryRecord(
@@ -80,15 +82,18 @@
)
return self._cachedRecords
+
def recordTypes(self):
return InternalDirectoryService.supportedRecordTypes
+
def listRecords(self, recordType):
if recordType not in InternalDirectoryService.supportedRecordTypes:
raise UnknownRecordTypeError(recordType)
return self._records()
+
def recordWithShortName(self, recordType, shortName):
if recordType not in InternalDirectoryService.supportedRecordTypes:
raise UnknownRecordTypeError(recordType)
@@ -97,11 +102,13 @@
if shortName in record.shortNames:
return record
+
def requestAvatarId(self, credentials):
credentials = IPrincipalCredentials(credentials)
raise UnauthorizedLogin("No such user: %s" % (credentials.credentials.username,))
+
class InternalDirectoryRecord(DirectoryRecord):
"""
L{DirectoryRecord} implementation for internal records.
@@ -121,5 +128,6 @@
self.enabled = True # Explicitly enabled
+
def verifyCredentials(self, credentials):
return False
Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -40,7 +40,6 @@
"LdapDirectoryService",
]
-import ldap
import ldap.async
from ldap.filter import escape_filter_chars as ldapEsc
Modified: CalendarServer/trunk/twistedcaldav/directory/resourceinfo.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/resourceinfo.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/resourceinfo.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -62,12 +62,14 @@
autoSchedule = None
returnValue(autoSchedule)
+
def __init__(self, path):
path = os.path.join(path, ResourceInfoDatabase.dbFilename)
super(ResourceInfoDatabase, self).__init__(path, True)
self._memcacher = ResourceInfoDatabase.ResourceInfoDBMemcacher("resourceInfoDB")
+
@inlineCallbacks
def setAutoSchedule(self, guid, autoSchedule):
"""
@@ -81,6 +83,7 @@
# Update cache
(yield self._memcacher.setAutoSchedule(guid, autoSchedule))
+
def setAutoScheduleInDatabase(self, guid, autoSchedule):
"""
A blocking call to set a resource/location's auto-Schedule boolean
@@ -94,6 +97,7 @@
self._add_to_db(guid, autoSchedule)
self._db_commit()
+
@inlineCallbacks
def getAutoSchedule(self, guid):
"""
@@ -110,6 +114,7 @@
(yield self._memcacher.setAutoSchedule(guid, autoSchedule))
returnValue(autoSchedule)
+
def _add_to_db(self, guid, autoSchedule):
"""
Insert the specified entry into the database.
@@ -124,6 +129,7 @@
""", guid, 1 if autoSchedule else 0
)
+
def _delete_from_db(self, guid):
"""
Deletes the specified entry from the database.
@@ -132,18 +138,21 @@
"""
self._db_execute("delete from RESOURCEINFO where GUID = :1", guid)
+
def _db_version(self):
"""
@return: the schema version assigned to this index.
"""
return ResourceInfoDatabase.dbFormatVersion
+
def _db_type(self):
"""
@return: the collection type assigned to this index.
"""
return ResourceInfoDatabase.dbType
+
def _db_init_data_tables(self, q):
"""
Initialise the underlying database tables.
@@ -166,4 +175,3 @@
create index RESOURCEGUIDS on RESOURCEINFO (GUID)
"""
)
-
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -200,7 +200,6 @@
)
-
class BuildFilterFromTokensTestCase(TestCase):
def test_buildFilterFromTokens(self):
@@ -300,7 +299,6 @@
)
-
class StubList(object):
def __init__(self, wrapper):
self.ldap = wrapper
@@ -320,13 +318,11 @@
attrlist=self.attrList)
-
class StubAsync(object):
def List(self, wrapper):
return StubList(wrapper)
-
class LdapDirectoryTestWrapper(object):
"""
A test stub which replaces search_s( ) with a version that will return
Modified: CalendarServer/trunk/twistedcaldav/directory/util.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/util.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/util.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -51,6 +51,7 @@
return normalizeUUID(str(uuid5(UUID(namespace), name)))
+
def normalizeUUID(value):
"""
Convert strings which the uuid.UUID( ) method can parse into normalized
@@ -106,6 +107,7 @@
return transaction
+
def splitIntoBatches(data, size):
"""
Return a generator of sets consisting of the contents of the data set
@@ -119,6 +121,7 @@
del data[:size]
+
class NotFoundResource(DAVResource):
"""
In order to prevent unauthenticated discovery of existing users via 401/404
@@ -131,7 +134,7 @@
def renderHTTP(self, request):
try:
- authnUser, authzUser = yield self.authenticate(request)
+ _ignore_authnUser, authzUser = yield self.authenticate(request)
except Exception:
authzUser = davxml.Principal(davxml.Unauthenticated())
@@ -145,4 +148,3 @@
else:
response = StatusResponse(responsecode.NOT_FOUND, "Resource not found")
returnValue(response)
-
Modified: CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -36,30 +36,30 @@
log = Logger()
-ELEMENT_ACCOUNTS = "accounts"
-ELEMENT_USER = "user"
-ELEMENT_GROUP = "group"
-ELEMENT_LOCATION = "location"
-ELEMENT_RESOURCE = "resource"
-ELEMENT_ADDRESS = "address"
+ELEMENT_ACCOUNTS = "accounts"
+ELEMENT_USER = "user"
+ELEMENT_GROUP = "group"
+ELEMENT_LOCATION = "location"
+ELEMENT_RESOURCE = "resource"
+ELEMENT_ADDRESS = "address"
-ELEMENT_SHORTNAME = "uid"
-ELEMENT_GUID = "guid"
-ELEMENT_PASSWORD = "password"
-ELEMENT_NAME = "name"
-ELEMENT_FIRST_NAME = "first-name"
-ELEMENT_LAST_NAME = "last-name"
-ELEMENT_EMAIL_ADDRESS = "email-address"
-ELEMENT_MEMBERS = "members"
-ELEMENT_MEMBER = "member"
-ELEMENT_EXTRAS = "extras"
+ELEMENT_SHORTNAME = "uid"
+ELEMENT_GUID = "guid"
+ELEMENT_PASSWORD = "password"
+ELEMENT_NAME = "name"
+ELEMENT_FIRST_NAME = "first-name"
+ELEMENT_LAST_NAME = "last-name"
+ELEMENT_EMAIL_ADDRESS = "email-address"
+ELEMENT_MEMBERS = "members"
+ELEMENT_MEMBER = "member"
+ELEMENT_EXTRAS = "extras"
-ATTRIBUTE_REALM = "realm"
-ATTRIBUTE_REPEAT = "repeat"
-ATTRIBUTE_RECORDTYPE = "type"
+ATTRIBUTE_REALM = "realm"
+ATTRIBUTE_REPEAT = "repeat"
+ATTRIBUTE_RECORDTYPE = "type"
-VALUE_TRUE = "true"
-VALUE_FALSE = "false"
+VALUE_TRUE = "true"
+VALUE_FALSE = "false"
RECORD_TYPES = {
ELEMENT_USER : DirectoryService.recordType_users,
@@ -76,6 +76,7 @@
def __repr__(self):
return "<%s %r>" % (self.__class__.__name__, self.xmlFile)
+
def __init__(self, xmlFile, externalUpdate=True):
if type(xmlFile) is str:
@@ -84,7 +85,7 @@
self.xmlFile = xmlFile
self.realm = None
self.items = {}
-
+
for recordType in RECORD_TYPES.values():
self.items[recordType] = {}
@@ -95,6 +96,7 @@
raise RuntimeError("XML parse error for '%s' because: %s" % (self.xmlFile, e,))
self._parseXML(accounts_node)
+
def _parseXML(self, node):
"""
Parse the XML root node from the accounts configuration document.
@@ -120,7 +122,7 @@
principal = XMLAccountRecord(recordType)
principal.parseXML(child)
if repeat > 0:
- for i in xrange(1, repeat+1):
+ for i in xrange(1, repeat + 1):
newprincipal = principal.repeat(i)
self.items[recordType][newprincipal.shortNames[0]] = newprincipal
else:
@@ -130,7 +132,9 @@
for records in self.items.itervalues():
for principal in records.itervalues():
updateMembership(principal)
-
+
+
+
class XMLAccountRecord (object):
"""
Contains provision information for one user.
@@ -151,6 +155,7 @@
self.groups = set()
self.extras = {}
+
def repeat(self, ctr):
"""
Create another object like this but with all text items having % substitution
@@ -183,7 +188,7 @@
if m:
length = int(m.group(0)[1:])
hash = hashlib.md5(str(ctr)).hexdigest()
- string = (hash*((length/32)+1))[:-(32-(length%32))]
+ string = (hash * ((length / 32) + 1))[:-(32 - (length % 32))]
return text.replace(m.group(0), string)
return text
@@ -223,7 +228,7 @@
emailAddresses.add(emailAddr % ctr)
else:
emailAddresses.add(emailAddr)
-
+
result = XMLAccountRecord(self.recordType)
result.shortNames = shortNames
result.guid = normalizeUUID(guid)
@@ -236,6 +241,7 @@
result.extras = self.extras
return result
+
def parseXML(self, node):
for child in node:
if child.tag == ELEMENT_SHORTNAME:
@@ -264,12 +270,14 @@
if not self.shortNames:
self.shortNames.append(self.guid)
+
def _parseMembers(self, node, addto):
for child in node:
if child.tag == ELEMENT_MEMBER:
recordType = child.get(ATTRIBUTE_RECORDTYPE, DirectoryService.recordType_users)
addto.add((recordType, child.text.encode("utf-8")))
+
def _parseExtras(self, node, addto):
for child in node:
addto[child.tag] = child.text.encode("utf-8")
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -6861,4 +6861,3 @@
aboMembers.REVISION.In(Parameter("revisionsToRemove", len(revisionsToRemove)))
)
).on(txn, revisionsToRemove=revisionsToRemove)
-
Modified: CalendarServer/trunk/txdav/idav.py
===================================================================
--- CalendarServer/trunk/txdav/idav.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/idav.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -240,9 +240,9 @@
types of changes to the appropriate push priority level.
TODO: make these values configurable in plist perhaps.
"""
- default = ValueConstant(PushPriority.high)
- inbox = ValueConstant(PushPriority.medium)
- attendeeITIPUpdate = ValueConstant(PushPriority.medium)
+ default = ValueConstant(PushPriority.high)
+ inbox = ValueConstant(PushPriority.medium)
+ attendeeITIPUpdate = ValueConstant(PushPriority.medium)
organizerITIPUpdate = ValueConstant(PushPriority.medium)
Modified: CalendarServer/trunk/txdav/xml/base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/base.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/base.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -80,6 +80,7 @@
return sname.encode("utf-8")
+
def decodeXMLName(name):
"""
Decodes an XML (namespace, name) pair from an ASCII string as
@@ -97,7 +98,7 @@
invalid()
namespace = name[1:index].decode("utf-8")
- localname = name[index+1:].decode("utf-8")
+ localname = name[index + 1:].decode("utf-8")
if not namespace:
namespace = None
@@ -108,24 +109,25 @@
else:
namespace = None
localname = name.decode("utf-8")
-
+
if "{" in localname or "}" in localname:
invalid()
return (namespace, localname)
+
class WebDAVElement (object):
"""
WebDAV XML element. (RFC 2518, section 12)
"""
- namespace = dav_namespace # Element namespace (class variable)
- name = None # Element name (class variable)
- allowed_children = None # Types & count limits on child elements
+ namespace = dav_namespace # Element namespace (class variable)
+ name = None # Element name (class variable)
+ allowed_children = None # Types & count limits on child elements
allowed_attributes = None # Allowed attribute names
- hidden = False # Don't list in PROPFIND with <allprop>
- protected = False # See RFC 3253 section 1.4.1
- unregistered = False # Subclass of factory; doesn't register
+ hidden = False # Don't list in PROPFIND with <allprop>
+ protected = False # See RFC 3253 section 1.4.1
+ unregistered = False # Subclass of factory; doesn't register
def __init__(self, *children, **attributes):
super(WebDAVElement, self).__init__()
@@ -138,7 +140,7 @@
my_children = []
- allowPCDATA = self.allowed_children.has_key(PCDATAElement)
+ allowPCDATA = PCDATAElement in self.allowed_children
for child in children:
if child is None:
@@ -155,14 +157,17 @@
self.children = tuple(my_children)
self.attributes = attributes
+
@classmethod
def qname(cls):
return (cls.namespace, cls.name)
+
@classmethod
def sname(cls):
return encodeXMLName(cls.namespace, cls.name)
+
def validate(self):
children = self.children
attributes = self.attributes
@@ -187,7 +192,7 @@
for child in children:
assert isinstance(child, (WebDAVElement, PCDATAElement)), "Not an element: %r" % (child,)
-
+
child.validate()
for allowed, (min, max) in allowed_children.items():
@@ -244,36 +249,43 @@
self.attributes = my_attributes
+
def __str__(self):
return self.sname()
+
def __repr__(self):
if hasattr(self, "attributes") and hasattr(self, "children"):
return "<%s %r: %r>" % (self.sname(), self.attributes, self.children)
else:
return "<%s>" % (self.sname())
+
def __eq__(self, other):
if isinstance(other, WebDAVElement):
return (
- self.name == other.name and
- self.namespace == other.namespace and
+ self.name == other.name and
+ self.namespace == other.namespace and
self.attributes == other.attributes and
- self.children == other.children
+ self.children == other.children
)
else:
return NotImplemented
+
def __ne__(self, other):
return not self.__eq__(other)
+
def __contains__(self, child):
return child in self.children
+
def writeXML(self, output, pretty=True):
output.write("<?xml version='1.0' encoding='UTF-8'?>" + ("\n" if pretty else ""))
self._writeToStream(output, "", 0, pretty)
+
def _writeToStream(self, output, ns, level, pretty):
"""
Fast XML output.
@@ -283,11 +295,11 @@
@param level: C{int} containing the element nesting level (starts at 0).
@param pretty: C{bool} whether to use 'pretty' formatted output or not.
"""
-
+
# Do pretty indent
if pretty and level:
output.write(" " * level)
-
+
# Check for empty element (one with either no children or a single PCDATA that is itself empty)
if (len(self.children) == 0 or
(len(self.children) == 1 and isinstance(self.children[0], PCDATAElement) and len(str(self.children[0])) == 0)):
@@ -314,7 +326,7 @@
output.write(">")
else:
output.write("<%s>" % (self.name,))
-
+
# Determine nature of children when doing pretty print: we do
# not want to insert CRLFs or any other whitespace in PCDATA.
hasPCDATA = False
@@ -322,13 +334,13 @@
if isinstance(child, PCDATAElement):
hasPCDATA = True
break
-
+
# Write out the children.
if pretty and not hasPCDATA:
output.write("\r\n")
for child in self.children:
- child._writeToStream(output, ns, level+1, pretty)
-
+ child._writeToStream(output, ns, level + 1, pretty)
+
# Close the element.
if pretty and not hasPCDATA and level:
output.write(" " * level)
@@ -337,18 +349,21 @@
if pretty and level:
output.write("\r\n")
+
def _writeAttributeToStream(self, output, name, value):
-
+
# Quote any single quotes. We do not need to be any smarter than this.
value = value.replace("'", "'")
- output.write(" %s='%s'" % (name, value,))
-
+ output.write(" %s='%s'" % (name, value,))
+
+
def toxml(self, pretty=True):
output = StringIO.StringIO()
self.writeXML(output, pretty)
return str(output.getvalue())
+
def element(self, document):
element = document.createElementNS(self.namespace, self.name)
if hasattr(self, "attributes"):
@@ -359,6 +374,7 @@
element.setAttributeNodeNS(attribute)
return element
+
def addToDOM(self, document, parent):
element = self.element(document)
@@ -375,6 +391,7 @@
log.error("Unable to add child %r of element %s to DOM" % (child, self))
raise
+
def childrenOfType(self, child_type):
"""
Returns a list of children with the same qname as the given type.
@@ -384,8 +401,9 @@
else:
qname = child_type.qname()
- return [ c for c in self.children if c.qname() == qname ]
+ return [c for c in self.children if c.qname() == qname]
+
def childOfType(self, child_type):
"""
Returns a child of the given type, if any, or None.
@@ -398,6 +416,7 @@
found = child
return found
+
def removeWhitespaceNodes(self):
""" Removes all of the whitespace-only text decendants of a DOM node. """
# prepare the list of text nodes to remove (and recurse when needed)
@@ -418,6 +437,7 @@
self.children = tuple(newchildren)
+
class PCDATAElement (object):
def __init__(self, data):
super(PCDATAElement, self).__init__()
@@ -431,29 +451,36 @@
self.data = data
+
@classmethod
def qname(cls):
return (None, "#PCDATA")
+
@classmethod
def sname(cls):
return "#PCDATA"
+
def validate(self):
pass
+
def __str__(self):
return str(self.data)
+
def __repr__(self):
return "<%s: %r>" % (self.__class__.__name__, self.data)
+
def __add__(self, other):
if isinstance(other, PCDATAElement):
return self.__class__(self.data + other.data)
else:
return self.__class__(self.data + other)
+
def __eq__(self, other):
if isinstance(other, PCDATAElement):
return self.data == other.data
@@ -462,18 +489,22 @@
else:
return NotImplemented
+
def __ne__(self, other):
return not self.__eq__(other)
+
def isWhitespace(self):
for char in str(self):
if char not in string.whitespace:
return False
return True
+
def element(self, document):
return document.createTextNode(self.data)
+
def addToDOM(self, document, parent):
try:
parent.appendChild(self.element(document))
@@ -481,6 +512,7 @@
log.error("Invalid PCDATA: %r" % (self.data,))
raise
+
def _writeToStream(self, output, ns, level, pretty):
# Do escaping/CDATA behavior
if "\r" in self.data or "\n" in self.data:
@@ -498,38 +530,40 @@
output.write(cdata)
+
class WebDAVOneShotElement (WebDAVElement):
"""
Element with exactly one WebDAVEmptyElement child and no attributes.
"""
__singletons = {}
- def __new__(clazz, *children):
+ def __new__(cls, *children):
child = None
for next in children:
if isinstance(next, WebDAVEmptyElement):
if child is not None:
raise ValueError("%s must have exactly one child, not %r"
- % (clazz.__name__, children))
+ % (cls.__name__, children))
child = next
elif isinstance(next, PCDATAElement):
pass
else:
raise ValueError("%s child is not a WebDAVEmptyElement instance: %s"
- % (clazz.__name__, next))
+ % (cls.__name__, next))
- if clazz not in WebDAVOneShotElement.__singletons:
- WebDAVOneShotElement.__singletons[clazz] = {
- child: WebDAVElement.__new__(clazz)
+ if cls not in WebDAVOneShotElement.__singletons:
+ WebDAVOneShotElement.__singletons[cls] = {
+ child: WebDAVElement.__new__(cls)
}
- elif child not in WebDAVOneShotElement.__singletons[clazz]:
- WebDAVOneShotElement.__singletons[clazz][child] = (
- WebDAVElement.__new__(clazz)
+ elif child not in WebDAVOneShotElement.__singletons[cls]:
+ WebDAVOneShotElement.__singletons[cls][child] = (
+ WebDAVElement.__new__(cls)
)
- return WebDAVOneShotElement.__singletons[clazz][child]
+ return WebDAVOneShotElement.__singletons[cls][child]
+
class WebDAVUnknownElement (WebDAVElement):
"""
Placeholder for unknown element tag names.
@@ -546,28 +580,31 @@
child.name = name
return child
+
def qname(self):
return (self.namespace, self.name)
+
def sname(self):
return encodeXMLName(self.namespace, self.name)
+
class WebDAVEmptyElement (WebDAVElement):
"""
WebDAV element with no contents.
"""
__singletons = {}
- def __new__(clazz, *args, **kwargs):
+ def __new__(cls, *args, **kwargs):
assert not args
if kwargs:
- return WebDAVElement.__new__(clazz)
+ return WebDAVElement.__new__(cls)
else:
- if clazz not in WebDAVEmptyElement.__singletons:
- WebDAVEmptyElement.__singletons[clazz] = (WebDAVElement.__new__(clazz))
- return WebDAVEmptyElement.__singletons[clazz]
+ if cls not in WebDAVEmptyElement.__singletons:
+ WebDAVEmptyElement.__singletons[cls] = (WebDAVElement.__new__(cls))
+ return WebDAVEmptyElement.__singletons[cls]
allowed_children = {}
children = ()
@@ -581,6 +618,7 @@
return hash((self.name, self.namespace))
+
class WebDAVTextElement (WebDAVElement):
"""
WebDAV element containing PCDATA.
@@ -594,7 +632,7 @@
else:
return clazz(PCDATAElement(str(string)))
- allowed_children = { PCDATAElement: (0, None) }
+ allowed_children = {PCDATAElement: (0, None)}
def toString(self):
"""
@@ -602,12 +640,14 @@
"""
return self.__str__().decode("utf-8")
+
def __str__(self):
"""
@return: a byte string containing the text in this element.
"""
return b"".join([c.data for c in self.children])
+
def __repr__(self):
content = str(self)
if content:
@@ -615,6 +655,7 @@
else:
return "<%s>" % (self.sname(),)
+
def __eq__(self, other):
if isinstance(other, self.__class__):
return str(self) == str(other)
@@ -624,6 +665,7 @@
return NotImplemented
+
class WebDAVDateTimeElement (WebDAVTextElement):
"""
WebDAV date-time element. (RFC 2518, section 23.2)
@@ -654,16 +696,19 @@
return clazz(PCDATAElement(date))
+
def __init__(self, *children, **attributes):
super(WebDAVDateTimeElement, self).__init__(*children, **attributes)
self.datetime() # Raise ValueError if the format is wrong
+
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.datetime() == other.datetime()
else:
return NotImplemented
+
def datetime(self):
s = str(self)
if not s:
@@ -672,6 +717,7 @@
return parse_date(s)
+
class DateTimeHeaderElement (WebDAVDateTimeElement):
"""
WebDAV date-time element for elements that substitute for HTTP
@@ -707,6 +753,7 @@
return clazz(PCDATAElement(date))
+
def datetime(self):
s = str(self)
if not s:
@@ -715,6 +762,7 @@
return parseDateTime(s)
+
##
# Utilities
##
@@ -727,13 +775,21 @@
super(FixedOffset, self).__init__()
self._offset = datetime.timedelta(minutes=offset)
- self._name = name
+ self._name = name
- def utcoffset(self, dt): return self._offset
- def tzname (self, dt): return self._name
- def dst (self, dt): return datetime.timedelta(0)
+ def utcoffset(self, dt):
+ return self._offset
+
+ def tzname(self, dt):
+ return self._name
+
+
+ def dst(self, dt):
+ return datetime.timedelta(0)
+
+
_regex_ISO8601Date = re.compile(
"^" +
"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T" +
@@ -760,19 +816,21 @@
if offset_sign is None:
offset = FixedOffset(0)
else:
- offset_hour = int(match.group("offset_hour" ))
+ offset_hour = int(match.group("offset_hour"))
offset_minute = int(match.group("offset_minute"))
delta = (offset_hour * 60) + offset_minute
- if offset_sign == "+": offset = FixedOffset(0 - delta)
- elif offset_sign == "-": offset = FixedOffset(0 + delta)
+ if offset_sign == "+":
+ offset = FixedOffset(0 - delta)
+ elif offset_sign == "-":
+ offset = FixedOffset(0 + delta)
return datetime.datetime(
- int(match.group("year" )),
- int(match.group("month" )),
- int(match.group("day" )),
- int(match.group("hour" )),
+ int(match.group("year")),
+ int(match.group("month")),
+ int(match.group("day")),
+ int(match.group("hour")),
int(match.group("minute")),
int(match.group("second")),
subsecond,
Modified: CalendarServer/trunk/txdav/xml/element.py
===================================================================
--- CalendarServer/trunk/txdav/xml/element.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/element.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -65,19 +65,20 @@
assert elementClass.name, "Element has no name: %s" % (elementClass,)
qname = elementClass.namespace, elementClass.name
-
+
if qname in _elements_by_qname:
raise AssertionError(
"Attempting to register element %s multiple times: (%r, %r)"
% (elementClass.sname(), _elements_by_qname[qname], elementClass)
)
-
+
if not (qname in _elements_by_qname and issubclass(elementClass, _elements_by_qname[qname])):
_elements_by_qname[qname] = elementClass
return elementClass
+
def registerElementClass(elementClass):
"""
Add an XML element class to this module's namespace.
@@ -97,6 +98,7 @@
return elementClass
+
def lookupElement(qname):
"""
Return the element class for the element with the given qname.
Modified: CalendarServer/trunk/txdav/xml/parser.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/parser.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Modified: CalendarServer/trunk/txdav/xml/parser_base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser_base.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/parser_base.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -37,6 +37,7 @@
def fromStream(cls, source):
raise NotImplementedError()
+
@classmethod
def fromString(cls, source):
source = StringIO(source)
@@ -45,6 +46,7 @@
finally:
source.close()
+
def __init__(self, root_element):
"""
root_element must be a WebDAVElement instance.
@@ -56,18 +58,22 @@
self.root_element = root_element
+
def __str__(self):
return self.toxml()
+
def __eq__(self, other):
if isinstance(other, AbstractWebDAVDocument):
return self.root_element == other.root_element
else:
return NotImplemented
+
def writeXML(self, output):
raise NotImplementedError()
+
def toxml(self):
output = StringIO()
self.writeXML(output)
Modified: CalendarServer/trunk/txdav/xml/parser_etree.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser_etree.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/parser_etree.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -28,7 +28,7 @@
"WebDAVDocument",
]
-from xml.etree.ElementTree import TreeBuilder, XMLParser,\
+from xml.etree.ElementTree import TreeBuilder, XMLParser, \
_namespace_map
from txdav.xml.base import WebDAVUnknownElement, PCDATAElement
from txdav.xml.base import _elements_by_qname
@@ -39,15 +39,19 @@
except ImportError:
from xml.parsers.expat import ExpatError as XMLParseError
+
+
def QNameSplit(qname):
return tuple(qname[1:].split("}", 1)) if "}" in qname else ("", qname,)
+
+
class WebDAVContentHandler (TreeBuilder):
def __init__(self):
TreeBuilder.__init__(self)
self._characterBuffer = None
-
+
self.startDocument()
@@ -56,7 +60,6 @@
Doctype declaration is ignored.
"""
-
def startDocument(self):
self.stack = [{
"name" : None,
@@ -71,6 +74,7 @@
# multiple times in a document.
self.unknownElementClasses = {}
+
def close(self):
top = self.stack[-1]
@@ -83,12 +87,14 @@
del(self.unknownElementClasses)
return self.dom
+
def data(self, data):
# Stash character data away in a list that we will "".join() when done
if self._characterBuffer is None:
self._characterBuffer = []
self._characterBuffer.append(data)
+
def start(self, tag, attrs):
name = QNameSplit(tag)
@@ -117,7 +123,7 @@
def element_class(*args, **kwargs):
element = WebDAVUnknownElement(*args, **kwargs)
element.namespace = tag_namespace
- element.name = tag_name
+ element.name = tag_name
return element
self.unknownElementClasses[name] = element_class
@@ -128,6 +134,7 @@
"children" : [],
})
+
def end(self, tag):
name = QNameSplit(tag)
@@ -149,10 +156,11 @@
self.stack[-1]["children"].append(element)
+
class WebDAVDocument(AbstractWebDAVDocument):
@classmethod
def fromStream(cls, source):
- parser = XMLParser(target=WebDAVContentHandler())
+ parser = XMLParser(target=WebDAVContentHandler())
try:
while 1:
data = source.read(65536)
@@ -162,6 +170,7 @@
except XMLParseError, e:
raise ValueError(e)
return parser.close()
-
+
+
def writeXML(self, output):
self.root_element.writeXML(output)
Modified: CalendarServer/trunk/txdav/xml/parser_sax.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser_sax.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/parser_sax.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -33,17 +33,22 @@
from txdav.xml.xmlext import Print as xmlPrint
-class WebDAVContentHandler (xml.sax.handler.ContentHandler):
- def setDocumentLocator(self, locator): self.locator = locator
+class WebDAVContentHandler(xml.sax.handler.ContentHandler):
+
+ def setDocumentLocator(self, locator):
+ self.locator = locator
+
locator = None
def __init__(self):
xml.sax.handler.ContentHandler.__init__(self)
self._characterBuffer = None
+
def location(self):
return "line %d, column %d" % (self.locator.getLineNumber(), self.locator.getColumnNumber())
+
def startDocument(self):
self.stack = [{
"name" : None,
@@ -58,6 +63,7 @@
# multiple times in a document.
self.unknownElementClasses = {}
+
def endDocument(self):
top = self.stack[-1]
@@ -69,6 +75,7 @@
self.dom = WebDAVDocument(top["children"][0])
del(self.unknownElementClasses)
+
def startElementNS(self, name, qname, attributes):
if self._characterBuffer is not None:
pcdata = PCDATAElement("".join(self._characterBuffer))
@@ -91,7 +98,7 @@
def element_class(*args, **kwargs):
element = WebDAVUnknownElement(*args, **kwargs)
element.namespace = tag_namespace
- element.name = tag_name
+ element.name = tag_name
return element
self.unknownElementClasses[name] = element_class
@@ -102,6 +109,7 @@
"children" : [],
})
+
def endElementNS(self, name, qname):
if self._characterBuffer is not None:
pcdata = PCDATAElement("".join(self._characterBuffer))
@@ -124,33 +132,41 @@
self.stack[-1]["children"].append(element)
+
def characters(self, content):
# Stash character data away in a list that we will "".join() when done
if self._characterBuffer is None:
self._characterBuffer = []
self._characterBuffer.append(content)
+
def ignorableWhitespace(self, whitespace):
self.characters(self, whitespace)
+
def startElement(self, name, attributes):
raise AssertionError("startElement() should not be called by namespace-aware parser")
+
def endElement(self, name):
raise AssertionError("endElement() should not be called by namespace-aware parser")
+
def processingInstruction(self, target, data):
raise AssertionError("processing instructions are not allowed")
+
def skippedEntity(self, name):
raise AssertionError("skipped entities are not allowed")
+
class WebDAVDocument(AbstractWebDAVDocument):
+
@classmethod
def fromStream(cls, source):
handler = WebDAVContentHandler()
- parser = xml.sax.make_parser()
+ parser = xml.sax.make_parser()
parser.setContentHandler(handler)
parser.setFeature(xml.sax.handler.feature_namespaces, True)
@@ -163,7 +179,8 @@
#handler.dom.root_element.validate()
return handler.dom
-
+
+
def writeXML(self, output):
document = xml.dom.minidom.Document()
self.root_element.addToDOM(document, None)
Modified: CalendarServer/trunk/txdav/xml/rfc2518.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc2518.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc2518.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -56,14 +56,15 @@
allowed_children = {
(dav_namespace, "lockscope"): (1, 1),
- (dav_namespace, "locktype" ): (1, 1),
- (dav_namespace, "depth" ): (1, 1),
- (dav_namespace, "owner" ): (0, 1),
- (dav_namespace, "timeout" ): (0, 1),
+ (dav_namespace, "locktype"): (1, 1),
+ (dav_namespace, "depth"): (1, 1),
+ (dav_namespace, "owner"): (0, 1),
+ (dav_namespace, "timeout"): (0, 1),
(dav_namespace, "locktoken"): (0, 1),
}
+
@registerElement
@registerElementClass
class Depth (WebDAVTextElement):
@@ -80,6 +81,7 @@
raise ValueError("Invalid depth: %s" % (depth,))
+
@registerElement
@registerElementClass
class LockToken (WebDAVElement):
@@ -88,9 +90,10 @@
"""
name = "locktoken"
- allowed_children = { (dav_namespace, "href"): (1, None) }
+ allowed_children = {(dav_namespace, "href"): (1, None)}
+
@registerElement
@registerElementClass
class Timeout (WebDAVTextElement):
@@ -100,6 +103,7 @@
name = "timeout"
+
@registerElement
@registerElementClass
class Collection (WebDAVEmptyElement):
@@ -109,6 +113,7 @@
name = "collection"
+
@registerElement
@registerElementClass
class HRef (WebDAVTextElement):
@@ -118,6 +123,7 @@
name = "href"
+
@registerElement
@registerElementClass
class Link (WebDAVElement):
@@ -133,6 +139,7 @@
}
+
@registerElement
@registerElementClass
class LinkDestination (WebDAVTextElement):
@@ -142,6 +149,7 @@
name = "dst"
+
@registerElement
@registerElementClass
class LinkSource (WebDAVTextElement):
@@ -151,6 +159,7 @@
name = "src"
+
@registerElement
@registerElementClass
class LockEntry (WebDAVElement):
@@ -162,10 +171,11 @@
allowed_children = {
(dav_namespace, "lockscope"): (1, 1),
- (dav_namespace, "locktype" ): (1, 1),
+ (dav_namespace, "locktype"): (1, 1),
}
+
@registerElement
@registerElementClass
class LockInfo (WebDAVElement):
@@ -177,11 +187,12 @@
allowed_children = {
(dav_namespace, "lockscope"): (1, 1),
- (dav_namespace, "locktype" ): (1, 1),
- (dav_namespace, "owner" ): (0, 1),
+ (dav_namespace, "locktype"): (1, 1),
+ (dav_namespace, "owner"): (0, 1),
}
+
@registerElement
@registerElementClass
class LockScope (WebDAVOneShotElement):
@@ -193,10 +204,11 @@
allowed_children = {
(dav_namespace, "exclusive"): (0, 1),
- (dav_namespace, "shared" ): (0, 1),
+ (dav_namespace, "shared"): (0, 1),
}
+
@registerElement
@registerElementClass
class Exclusive (WebDAVEmptyElement):
@@ -227,9 +239,10 @@
"""
name = "locktype"
- allowed_children = { (dav_namespace, "write"): (0, 1) }
+ allowed_children = {(dav_namespace, "write"): (0, 1)}
+
@registerElement
@registerElementClass
class Write (WebDAVEmptyElement):
@@ -253,11 +266,12 @@
name = "multistatus"
allowed_children = {
- (dav_namespace, "response" ): (0, None),
+ (dav_namespace, "response"): (0, None),
(dav_namespace, "responsedescription"): (0, 1),
}
+
@registerElement
@registerElementClass
class Response (WebDAVElement):
@@ -268,46 +282,51 @@
name = "response"
allowed_children = {
- (dav_namespace, "href" ): (1, None),
- (dav_namespace, "status" ): (1, 1),
- (dav_namespace, "propstat" ): (1, None),
- (dav_namespace, "error" ): (0, 1), # 2518bis
+ (dav_namespace, "href"): (1, None),
+ (dav_namespace, "status"): (1, 1),
+ (dav_namespace, "propstat"): (1, None),
+ (dav_namespace, "error"): (0, 1), # 2518bis
(dav_namespace, "responsedescription"): (0, 1),
}
- def __new__(clazz, *children):
- if clazz is not Response: return WebDAVElement.__new__(clazz)
+ def __new__(cls, *children):
+ if cls is not Response:
+ return WebDAVElement.__new__(cls)
resource_count = 0
- status_count = 0
+ status_count = 0
propstat_count = 0
for child in children:
- if isinstance(child, HRef ): resource_count += 1
- elif isinstance(child, Status ): status_count += 1
- elif isinstance(child, PropertyStatus): propstat_count += 1
+ if isinstance(child, HRef):
+ resource_count += 1
+ elif isinstance(child, Status):
+ status_count += 1
+ elif isinstance(child, PropertyStatus):
+ propstat_count += 1
if resource_count < 1:
raise ValueError("%s element must have at least one %s."
- % (clazz.sname(), HRef.sname()))
+ % (cls.sname(), HRef.sname()))
if status_count is 0:
if propstat_count is 0:
raise ValueError("%s element must have one of %s or %s"
- % (clazz.sname(), Status.sname(), PropertyStatus.sname()))
+ % (cls.sname(), Status.sname(), PropertyStatus.sname()))
if resource_count > 1:
raise ValueError("%s element with %s may only have one %s"
- % (clazz.sname(), PropertyStatus.sname(), HRef.sname()))
+ % (cls.sname(), PropertyStatus.sname(), HRef.sname()))
return PropertyStatusResponse.__new__(PropertyStatusResponse, *children)
if status_count > 1:
- raise ValueError("%s element may only have one %s" % (clazz.sname(), Status.sname()))
+ raise ValueError("%s element may only have one %s" % (cls.sname(), Status.sname()))
return StatusResponse.__new__(StatusResponse, *children)
+
@registerElementClass
class StatusResponse (Response):
"""
@@ -316,13 +335,14 @@
unregistered = True
allowed_children = {
- (dav_namespace, "href" ): (1, None),
- (dav_namespace, "status" ): (1, 1),
- (dav_namespace, "error" ): (0, 1), # 2518bis
+ (dav_namespace, "href"): (1, None),
+ (dav_namespace, "status"): (1, 1),
+ (dav_namespace, "error"): (0, 1), # 2518bis
(dav_namespace, "responsedescription"): (0, 1),
}
+
@registerElementClass
class PropertyStatusResponse (Response):
"""
@@ -331,13 +351,14 @@
unregistered = True
allowed_children = {
- (dav_namespace, "href" ): (1, 1),
- (dav_namespace, "propstat" ): (1, None),
- (dav_namespace, "error" ): (0, 1), # 2518bis
+ (dav_namespace, "href"): (1, 1),
+ (dav_namespace, "propstat"): (1, None),
+ (dav_namespace, "error"): (0, 1), # 2518bis
(dav_namespace, "responsedescription"): (0, 1),
}
+
@registerElement
@registerElementClass
class PropertyStatus (WebDAVElement):
@@ -348,13 +369,14 @@
name = "propstat"
allowed_children = {
- (dav_namespace, "prop" ): (1, 1),
- (dav_namespace, "status" ): (1, 1),
- (dav_namespace, "error" ): (0, 1), # 2518bis
+ (dav_namespace, "prop"): (1, 1),
+ (dav_namespace, "status"): (1, 1),
+ (dav_namespace, "error"): (0, 1), # 2518bis
(dav_namespace, "responsedescription"): (0, 1),
}
+
@registerElement
@registerElementClass
class Status (WebDAVTextElement):
@@ -363,6 +385,7 @@
"""
name = "status"
+ @classmethod
def fromResponseCode(clazz, code):
"""
code must be an integer response code in
@@ -373,7 +396,6 @@
return clazz(PCDATAElement("HTTP/1.1 %d %s" % (code, responsecode.RESPONSES[code])))
- fromResponseCode = classmethod(fromResponseCode)
def __init__(self, *children, **attributes):
super(Status, self).__init__(*children, **attributes)
@@ -389,6 +411,7 @@
self.code = code
+
@registerElement
@registerElementClass
class ResponseDescription (WebDAVTextElement):
@@ -399,6 +422,7 @@
name = "responsedescription"
+
@registerElement
@registerElementClass
class Owner (WebDAVElement):
@@ -414,9 +438,10 @@
hidden = True
protected = True # may be protected, per RFC 3744, section 5.1
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
+
@registerElement
@registerElementClass
class PropertyContainer (WebDAVElement):
@@ -425,9 +450,10 @@
"""
name = "prop"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
+
@registerElement
@registerElementClass
class PropertyBehavior (WebDAVElement):
@@ -438,7 +464,7 @@
name = "propertybehavior"
allowed_children = {
- (dav_namespace, "omit" ): (0, 1),
+ (dav_namespace, "omit"): (0, 1),
(dav_namespace, "keepalive"): (0, 1),
}
@@ -454,6 +480,7 @@
self.behavior = children[0]
+
@registerElement
@registerElementClass
class KeepAlive (WebDAVElement):
@@ -487,6 +514,7 @@
raise ValueError("Invalid keepalive value: %r", (str(self),))
+
@registerElement
@registerElementClass
class Omit (WebDAVEmptyElement):
@@ -497,6 +525,7 @@
name = "omit"
+
@registerElement
@registerElementClass
class PropertyUpdate (WebDAVElement):
@@ -508,10 +537,11 @@
allowed_children = {
(dav_namespace, "remove"): (0, None),
- (dav_namespace, "set" ): (0, None),
+ (dav_namespace, "set"): (0, None),
}
+
@registerElement
@registerElementClass
class Remove (WebDAVElement):
@@ -521,9 +551,10 @@
"""
name = "remove"
- allowed_children = { (dav_namespace, "prop"): (1, 1) }
+ allowed_children = {(dav_namespace, "prop"): (1, 1)}
+
@registerElement
@registerElementClass
class Set (WebDAVElement):
@@ -533,9 +564,10 @@
"""
name = "set"
- allowed_children = { (dav_namespace, "prop"): (1, 1) }
+ allowed_children = {(dav_namespace, "prop"): (1, 1)}
+
@registerElement
@registerElementClass
class PropertyFind (WebDAVElement):
@@ -546,9 +578,9 @@
name = "propfind"
allowed_children = {
- (dav_namespace, "allprop" ): (0, 1),
+ (dav_namespace, "allprop"): (0, 1),
(dav_namespace, "propname"): (0, 1),
- (dav_namespace, "prop" ): (0, 1),
+ (dav_namespace, "prop"): (0, 1),
}
def validate(self):
@@ -561,6 +593,7 @@
)
+
@registerElement
@registerElementClass
class AllProperties (WebDAVEmptyElement):
@@ -571,6 +604,7 @@
name = "allprop"
+
@registerElement
@registerElementClass
class PropertyName (WebDAVEmptyElement):
@@ -581,6 +615,7 @@
name = "propname"
+
##
# Section 13
##
@@ -597,6 +632,7 @@
protected = True
+
@registerElement
@registerElementClass
class DisplayName (WebDAVTextElement):
@@ -607,6 +643,7 @@
name = "displayname"
+
@registerElement
@registerElementClass
class GETContentLanguage (WebDAVTextElement):
@@ -617,6 +654,7 @@
name = "getcontentlanguage"
+
@registerElement
@registerElementClass
class GETContentLength (WebDAVTextElement):
@@ -628,6 +666,7 @@
protected = True
+
@registerElement
@registerElementClass
class GETContentType (WebDAVTextElement):
@@ -641,6 +680,7 @@
return MimeType.fromString(str(self))
+
@registerElement
@registerElementClass
class GETETag (WebDAVTextElement):
@@ -652,6 +692,7 @@
protected = True
+
@registerElement
@registerElementClass
class GETLastModified (DateTimeHeaderElement):
@@ -663,6 +704,7 @@
protected = True
+
@registerElement
@registerElementClass
class LockDiscovery (WebDAVElement):
@@ -672,9 +714,10 @@
name = "lockdiscovery"
protected = True
- allowed_children = { (dav_namespace, "activelock"): (0, None) }
+ allowed_children = {(dav_namespace, "activelock"): (0, None)}
+
@registerElement
@registerElementClass
class ResourceType (WebDAVElement):
@@ -684,10 +727,10 @@
name = "resourcetype"
protected = True
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
ResourceType.collection = ResourceType(Collection())
-ResourceType.empty = ResourceType()
+ResourceType.empty = ResourceType()
@registerElement
@@ -700,9 +743,10 @@
"""
name = "source"
- allowed_children = { (dav_namespace, "link"): (0, None) }
+ allowed_children = {(dav_namespace, "link"): (0, None)}
+
@registerElement
@registerElementClass
class SupportedLock (WebDAVElement):
@@ -713,12 +757,12 @@
name = "supportedlock"
protected = True
- allowed_children = { (dav_namespace, "lockentry"): (0, None) }
+ allowed_children = {(dav_namespace, "lockentry"): (0, None)}
+
# FIXME: Add preconditions codes defined in RFC4918
-
@registerElement
@registerElementClass
class PropfindFiniteDepth (WebDAVEmptyElement):
Modified: CalendarServer/trunk/txdav/xml/rfc3253.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc3253.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc3253.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -49,9 +49,10 @@
# FIXME: Move when we update to RFC 2518bis
name = "error"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
+
##
# Section 3
##
@@ -68,6 +69,7 @@
hidden = True
+
@registerElement
@registerElementClass
class CreatorDisplayName (WebDAVTextElement):
@@ -79,6 +81,7 @@
hidden = True
+
@registerElement
@registerElementClass
class SupportedMethod (WebDAVElement):
@@ -92,10 +95,11 @@
name = "supported-method"
hidden = True
- allowed_children = { WebDAVElement: (0, None) }
- allowed_attributes = { "name": True }
+ allowed_children = {WebDAVElement: (0, None)}
+ allowed_attributes = {"name": True}
+
@registerElement
@registerElementClass
class SupportedMethodSet (WebDAVElement):
@@ -107,9 +111,10 @@
protected = True
hidden = True
- allowed_children = { (dav_namespace, "supported-method"): (0, None) }
+ allowed_children = {(dav_namespace, "supported-method"): (0, None)}
+
@registerElement
@registerElementClass
class SupportedLiveProperty (WebDAVElement):
@@ -124,9 +129,10 @@
name = "supported-live-property"
# FIXME: Where is the name element defined?
- allowed_children = { (dav_namespace, "name"): (1, 1) }
+ allowed_children = {(dav_namespace, "name"): (1, 1)}
+
@registerElement
@registerElementClass
class SupportedLivePropertySet (WebDAVElement):
@@ -138,9 +144,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "supported-live-property"): (0, None) }
+ allowed_children = {(dav_namespace, "supported-live-property"): (0, None)}
+
@registerElement
@registerElementClass
class Report (WebDAVElement):
@@ -150,9 +157,10 @@
# FIXME: Section 3.1.5 is pretty low on information. Where else do we look?
name = "report"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
+
@registerElement
@registerElementClass
class SupportedReport (WebDAVElement):
@@ -185,9 +193,10 @@
# Absent any better guidance, we'll allow no children for this element for
# the time being.
#
- allowed_children = { (dav_namespace, "report"): (0, 1) }
+ allowed_children = {(dav_namespace, "report"): (0, 1)}
+
@registerElement
@registerElementClass
class SupportedReportSet (WebDAVElement):
@@ -199,9 +208,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "supported-report"): (0, None) }
+ allowed_children = {(dav_namespace, "supported-report"): (0, None)}
+
@registerElement
@registerElementClass
class ExpandProperty (WebDAVElement):
@@ -212,9 +222,10 @@
"""
name = "expand-property"
- allowed_children = { (dav_namespace, "property"): (0, None) }
+ allowed_children = {(dav_namespace, "property"): (0, None)}
+
@registerElement
@registerElementClass
class Property (WebDAVElement):
@@ -227,7 +238,7 @@
"""
name = "property"
- allowed_children = { (dav_namespace, "property"): (0, None) }
+ allowed_children = {(dav_namespace, "property"): (0, None)}
allowed_attributes = {
"name" : True,
"namespace" : False,
Modified: CalendarServer/trunk/txdav/xml/rfc3744.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc3744.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc3744.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -51,6 +51,7 @@
name = "read"
+
# For DAV:write element (RFC 3744, section 3.2) see Write class in
# rfc2518.py.
@@ -65,6 +66,7 @@
name = "write-properties"
+
@registerElement
@registerElementClass
class WriteContent (WebDAVEmptyElement):
@@ -75,6 +77,7 @@
name = "write-content"
+
@registerElement
@registerElementClass
class Unlock (WebDAVEmptyElement):
@@ -85,6 +88,7 @@
name = "unlock"
+
@registerElement
@registerElementClass
class ReadACL (WebDAVEmptyElement):
@@ -95,6 +99,7 @@
name = "read-acl"
+
@registerElement
@registerElementClass
class ReadCurrentUserPrivilegeSet (WebDAVEmptyElement):
@@ -106,6 +111,7 @@
name = "read-current-user-privilege-set"
+
@registerElement
@registerElementClass
class WriteACL (WebDAVEmptyElement):
@@ -116,6 +122,7 @@
name = "write-acl"
+
@registerElement
@registerElementClass
class Bind (WebDAVEmptyElement):
@@ -126,6 +133,7 @@
name = "bind"
+
@registerElement
@registerElementClass
class Unbind (WebDAVEmptyElement):
@@ -136,6 +144,7 @@
name = "unbind"
+
@registerElement
@registerElementClass
class All (WebDAVEmptyElement):
@@ -147,6 +156,7 @@
name = "all"
+
##
# Section 4 (Principal Properties)
##
@@ -161,12 +171,12 @@
name = "principal"
allowed_children = {
- (dav_namespace, "href" ): (0, 1),
- (dav_namespace, "all" ): (0, 1),
- (dav_namespace, "authenticated" ): (0, 1),
+ (dav_namespace, "href"): (0, 1),
+ (dav_namespace, "all"): (0, 1),
+ (dav_namespace, "authenticated"): (0, 1),
(dav_namespace, "unauthenticated"): (0, 1),
- (dav_namespace, "property" ): (0, 1),
- (dav_namespace, "self" ): (0, 1),
+ (dav_namespace, "property"): (0, 1),
+ (dav_namespace, "self"): (0, 1),
}
def validate(self):
@@ -181,6 +191,7 @@
)
+
@registerElement
@registerElementClass
class AlternateURISet (WebDAVElement):
@@ -192,9 +203,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, None) }
+ allowed_children = {(dav_namespace, "href"): (0, None)}
+
@registerElement
@registerElementClass
class PrincipalURL (WebDAVElement):
@@ -206,9 +218,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, 1) }
+ allowed_children = {(dav_namespace, "href"): (0, 1)}
+
@registerElement
@registerElementClass
class GroupMemberSet (WebDAVElement):
@@ -220,9 +233,10 @@
name = "group-member-set"
hidden = True
- allowed_children = { (dav_namespace, "href"): (0, None) }
+ allowed_children = {(dav_namespace, "href"): (0, None)}
+
@registerElement
@registerElementClass
class GroupMembership (WebDAVElement):
@@ -234,9 +248,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, None) }
+ allowed_children = {(dav_namespace, "href"): (0, None)}
+
##
# Section 5 (Access Control Properties)
##
@@ -256,9 +271,10 @@
hidden = True
protected = True # may be protected, per RFC 3744, section 5.2
- allowed_children = { (dav_namespace, "href"): (0, 1) }
+ allowed_children = {(dav_namespace, "href"): (0, 1)}
+
@registerElement
@registerElementClass
class SupportedPrivilegeSet (WebDAVElement):
@@ -270,9 +286,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "supported-privilege"): (0, None) }
+ allowed_children = {(dav_namespace, "supported-privilege"): (0, None)}
+
@registerElement
@registerElementClass
class SupportedPrivilege (WebDAVElement):
@@ -282,13 +299,14 @@
name = "supported-privilege"
allowed_children = {
- (dav_namespace, "privilege" ): (1, 1),
- (dav_namespace, "abstract" ): (0, 1),
- (dav_namespace, "description" ): (1, 1),
+ (dav_namespace, "privilege"): (1, 1),
+ (dav_namespace, "abstract"): (0, 1),
+ (dav_namespace, "description"): (1, 1),
(dav_namespace, "supported-privilege"): (0, None),
}
+
@registerElement
@registerElementClass
class Privilege (WebDAVElement):
@@ -297,7 +315,7 @@
"""
name = "privilege"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
def isAggregateOf(self, subprivilege, supportedPrivileges):
"""
@@ -339,6 +357,7 @@
else:
return False
+
def expandAggregate(self, supportedPrivileges):
"""
Expand this privilege into the set of privileges aggregated under it
@@ -384,6 +403,7 @@
return aggregates
+
@registerElement
@registerElementClass
class Abstract (WebDAVElement):
@@ -393,6 +413,7 @@
name = "abstract"
+
@registerElement
@registerElementClass
class Description (WebDAVTextElement):
@@ -401,9 +422,10 @@
3744, sections 5.3 and 9.5)
"""
name = "description"
- allowed_attributes = { "xml:lang": True }
+ allowed_attributes = {"xml:lang": True}
+
@registerElement
@registerElementClass
class CurrentUserPrivilegeSet (WebDAVElement):
@@ -416,9 +438,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "privilege"): (0, None) }
+ allowed_children = {(dav_namespace, "privilege"): (0, None)}
+
# For DAV:privilege element (RFC 3744, section 5.4) see Privilege class above.
@@ -434,9 +457,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "ace"): (0, None) }
+ allowed_children = {(dav_namespace, "ace"): (0, None)}
+
@registerElement
@registerElementClass
class ACE (WebDAVElement):
@@ -448,9 +472,9 @@
allowed_children = {
(dav_namespace, "principal"): (0, 1),
- (dav_namespace, "invert" ): (0, 1),
- (dav_namespace, "grant" ): (0, 1),
- (dav_namespace, "deny" ): (0, 1),
+ (dav_namespace, "invert"): (0, 1),
+ (dav_namespace, "grant"): (0, 1),
+ (dav_namespace, "deny"): (0, 1),
(dav_namespace, "protected"): (0, 1),
(dav_namespace, "inherited"): (0, 1),
}
@@ -458,12 +482,12 @@
def __init__(self, *children, **attributes):
super(ACE, self).__init__(*children, **attributes)
- self.principal = None
- self.invert = None
- self.allow = None
+ self.principal = None
+ self.invert = None
+ self.allow = None
self.privileges = None
- self.inherited = None
- self.protected = False
+ self.inherited = None
+ self.protected = False
my_children = []
@@ -481,24 +505,24 @@
% (self.sname(), self.children)
)
if name == "invert":
- self.invert = True
+ self.invert = True
self.principal = child.children[0]
else:
- self.invert = False
+ self.invert = False
self.principal = child
-
+
elif name in ("grant", "deny"):
if self.allow is not None:
raise ValueError(
"Only one of DAV:grant or DAV:deny allowed in %s, got: %s"
% (self.sname(), self.children)
)
- self.allow = (name == "grant")
+ self.allow = (name == "grant")
self.privileges = child.children
-
+
elif name == "inherited":
self.inherited = str(child.children[0])
-
+
elif name == "protected":
self.protected = True
@@ -525,6 +549,7 @@
# class above.
+
# For DAV:all element (RFC 3744, section 5.5.1) see All class above.
@@ -537,6 +562,7 @@
name = "authenticated"
+
@registerElement
@registerElementClass
class Unauthenticated (WebDAVEmptyElement):
@@ -546,6 +572,7 @@
name = "unauthenticated"
+
# For DAV:property element (RFC 3744, section 5.5.1) see Property
# class above.
@@ -560,6 +587,7 @@
name = "self"
+
@registerElement
@registerElementClass
class Invert (WebDAVElement):
@@ -569,9 +597,10 @@
"""
name = "invert"
- allowed_children = { (dav_namespace, "principal"): (1, 1) }
+ allowed_children = {(dav_namespace, "principal"): (1, 1)}
+
@registerElement
@registerElementClass
class Grant (WebDAVElement):
@@ -580,9 +609,10 @@
"""
name = "grant"
- allowed_children = { (dav_namespace, "privilege"): (1, None) }
+ allowed_children = {(dav_namespace, "privilege"): (1, None)}
+
@registerElement
@registerElementClass
class Deny (WebDAVElement):
@@ -591,9 +621,10 @@
"""
name = "deny"
- allowed_children = { (dav_namespace, "privilege"): (1, None) }
+ allowed_children = {(dav_namespace, "privilege"): (1, None)}
+
# For DAV:privilege element (RFC 3744, section 5.5.2) see Privilege
# class above.
@@ -607,18 +638,20 @@
name = "protected"
+
@registerElement
@registerElementClass
class Inherited (WebDAVElement):
"""
- Indicates that an ACE is inherited from the resource indentified by the
+ Indicates that an ACE is inherited from the resource identified by the
contained DAV:href element. (RFC 3744, section 5.5.4)
"""
name = "inherited"
- allowed_children = { (dav_namespace, "href"): (1, 1) }
+ allowed_children = {(dav_namespace, "href"): (1, 1)}
+
@registerElement
@registerElementClass
class ACLRestrictions (WebDAVElement):
@@ -631,13 +664,14 @@
protected = True
allowed_children = {
- (dav_namespace, "grant-only" ): (0, 1),
- (dav_namespace, "no-invert" ): (0, 1),
- (dav_namespace, "deny-before-grant" ): (0, 1),
+ (dav_namespace, "grant-only"): (0, 1),
+ (dav_namespace, "no-invert"): (0, 1),
+ (dav_namespace, "deny-before-grant"): (0, 1),
(dav_namespace, "required-principal"): (0, 1),
}
+
@registerElement
@registerElementClass
class GrantOnly (WebDAVEmptyElement):
@@ -648,6 +682,7 @@
name = "grant-only"
+
@registerElement
@registerElementClass
class NoInvert (WebDAVEmptyElement):
@@ -658,6 +693,7 @@
name = "no-invert"
+
@registerElement
@registerElementClass
class DenyBeforeGrant (WebDAVEmptyElement):
@@ -668,6 +704,7 @@
name = "deny-before-grant"
+
@registerElement
@registerElementClass
class RequiredPrincipal (WebDAVElement):
@@ -678,12 +715,12 @@
name = "required-principal"
allowed_children = {
- (dav_namespace, "all" ): (0, 1),
- (dav_namespace, "authenticated" ): (0, 1),
+ (dav_namespace, "all"): (0, 1),
+ (dav_namespace, "authenticated"): (0, 1),
(dav_namespace, "unauthenticated"): (0, 1),
- (dav_namespace, "self" ): (0, 1),
- (dav_namespace, "href" ): (0, None),
- (dav_namespace, "property" ): (0, None),
+ (dav_namespace, "self"): (0, 1),
+ (dav_namespace, "href"): (0, None),
+ (dav_namespace, "property"): (0, None),
}
def validate(self):
@@ -702,6 +739,7 @@
)
+
@registerElement
@registerElementClass
class InheritedACLSet (WebDAVElement):
@@ -713,9 +751,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, None) }
+ allowed_children = {(dav_namespace, "href"): (0, None)}
+
@registerElement
@registerElementClass
class PrincipalCollectionSet (WebDAVElement):
@@ -728,9 +767,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, None) }
+ allowed_children = {(dav_namespace, "href"): (0, None)}
+
##
# Section 7 (Access Control and existing methods)
##
@@ -743,9 +783,10 @@
"""
name = "need-privileges"
- allowed_children = { (dav_namespace, "resource"): (0, None) }
+ allowed_children = {(dav_namespace, "resource"): (0, None)}
+
@registerElement
@registerElementClass
class Resource (WebDAVElement):
@@ -756,11 +797,12 @@
name = "resource"
allowed_children = {
- (dav_namespace, "href" ): (1, 1),
+ (dav_namespace, "href"): (1, 1),
(dav_namespace, "privilege"): (1, 1),
}
+
##
# Section 9 (Access Control Reports)
##
@@ -776,13 +818,13 @@
"""
name = "acl-principal-prop-set"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
def validate(self):
super(ACLPrincipalPropSet, self).validate()
prop = False
-
+
for child in self.children:
if child.qname() == (dav_namespace, "prop"):
if prop:
@@ -793,6 +835,7 @@
prop = True
+
@registerElement
@registerElementClass
class PrincipalMatch (WebDAVElement):
@@ -805,8 +848,8 @@
allowed_children = {
(dav_namespace, "principal-property"): (0, 1),
- (dav_namespace, "self" ): (0, 1),
- (dav_namespace, "prop" ): (0, 1),
+ (dav_namespace, "self"): (0, 1),
+ (dav_namespace, "prop"): (0, 1),
}
def validate(self):
@@ -836,6 +879,7 @@
)
+
@registerElement
@registerElementClass
class PrincipalProperty (WebDAVElement):
@@ -844,9 +888,10 @@
"""
name = "principal-property"
- allowed_children = { WebDAVElement: (0, None) }
+ allowed_children = {WebDAVElement: (0, None)}
+
# For DAV:self element (RFC 3744, section 9.3) see Self class above.
@@ -861,13 +906,14 @@
name = "principal-property-search"
allowed_children = {
- (dav_namespace, "property-search" ): (0, None), # This is required but this element must be empty in supported-report-set
- (dav_namespace, "prop" ): (0, 1),
+ (dav_namespace, "property-search"): (0, None), # This is required but this element must be empty in supported-report-set
+ (dav_namespace, "prop"): (0, 1),
(dav_namespace, "apply-to-principal-collection-set"): (0, 1),
}
- allowed_attributes = { "test": False }
+ allowed_attributes = {"test": False}
+
@registerElement
@registerElementClass
class PropertySearch (WebDAVElement):
@@ -878,11 +924,12 @@
name = "property-search"
allowed_children = {
- (dav_namespace, "prop" ): (1, 1),
+ (dav_namespace, "prop"): (1, 1),
(dav_namespace, "match"): (1, 1),
}
+
@registerElement
@registerElementClass
class Match (WebDAVTextElement):
@@ -892,6 +939,7 @@
name = "match"
+
@registerElement
@registerElementClass
class PrincipalSearchPropertySet (WebDAVElement):
@@ -901,9 +949,10 @@
"""
name = "principal-search-property-set"
- allowed_children = { (dav_namespace, "principal-search-property"): (0, None) }
+ allowed_children = {(dav_namespace, "principal-search-property"): (0, None)}
+
@registerElement
@registerElementClass
class PrincipalSearchProperty (WebDAVElement):
@@ -914,11 +963,12 @@
name = "principal-search-property"
allowed_children = {
- (dav_namespace, "prop" ): (1, 1),
+ (dav_namespace, "prop"): (1, 1),
(dav_namespace, "description"): (1, 1),
}
+
@registerElement
@registerElementClass
class NumberOfMatchesWithinLimits (WebDAVEmptyElement):
Modified: CalendarServer/trunk/txdav/xml/rfc4331.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc4331.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc4331.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -51,6 +51,7 @@
protected = True
+
@registerElement
@registerElementClass
class QuotaUsedBytes (WebDAVTextElement):
Modified: CalendarServer/trunk/txdav/xml/rfc5397.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5397.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc5397.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Modified: CalendarServer/trunk/txdav/xml/rfc5842.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5842.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc5842.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -45,9 +45,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, 1) }
+ allowed_children = {(dav_namespace, "href"): (0, 1)}
+
@registerElement
@registerElementClass
class ParentSet (WebDAVElement):
@@ -58,9 +59,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "parent"): (0, 1) }
+ allowed_children = {(dav_namespace, "parent"): (0, 1)}
+
@registerElement
@registerElementClass
class Parent (WebDAVElement):
@@ -73,6 +75,7 @@
}
+
@registerElement
@registerElementClass
class Segment (WebDAVTextElement):
Modified: CalendarServer/trunk/txdav/xml/rfc5995.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5995.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/rfc5995.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -48,9 +48,10 @@
hidden = True
protected = True
- allowed_children = { (dav_namespace, "href"): (0, 1) }
+ allowed_children = {(dav_namespace, "href"): (0, 1)}
+
@registerElement
@registerElementClass
class AllowClientDefinedURI (WebDAVElement):
Modified: CalendarServer/trunk/txdav/xml/test/test_base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_base.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/test/test_base.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -37,7 +37,7 @@
"""
def test_decodeXMLName(self):
# Empty name
- self.assertRaises(ValueError, decodeXMLName, "")
+ self.assertRaises(ValueError, decodeXMLName, "")
self.assertRaises(ValueError, decodeXMLName, "{}")
self.assertRaises(ValueError, decodeXMLName, "{x}")
@@ -47,18 +47,19 @@
self.assertRaises(ValueError, decodeXMLName, "{x")
self.assertRaises(ValueError, decodeXMLName, "}")
self.assertRaises(ValueError, decodeXMLName, "x}")
- self.assertRaises(ValueError, decodeXMLName, "}x")
+ self.assertRaises(ValueError, decodeXMLName, "}x")
self.assertRaises(ValueError, decodeXMLName, "{{}")
self.assertRaises(ValueError, decodeXMLName, "{{}}")
self.assertRaises(ValueError, decodeXMLName, "x{}")
# Empty namespace is OK
- self.assertEquals(decodeXMLName( "x"), (None, "x"))
+ self.assertEquals(decodeXMLName("x"), (None, "x"))
self.assertEquals(decodeXMLName("{}x"), (None, "x"))
# Normal case
self.assertEquals(decodeXMLName("{namespace}name"), ("namespace", "name"))
+
def test_encodeXMLName(self):
# No namespace
self.assertEquals(encodeXMLName(None, "name"), "name")
@@ -68,6 +69,7 @@
self.assertEquals(encodeXMLName("namespace", "name"), "{namespace}name")
+
class WebDAVElementTestsMixin:
"""
Mixin for L{TestCase}s which test a L{WebDAVElement} subclass.
@@ -92,6 +94,7 @@
WebDAVDocument.fromString(document.toxml()))
+
class WebDAVUnknownElementTests(WebDAVElementTestsMixin, TestCase):
"""
Tests for L{WebDAVUnknownElement}.
Modified: CalendarServer/trunk/txdav/xml/test/test_xml.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_xml.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/test/test_xml.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -54,6 +54,7 @@
)
+
class CurrentUserPrincipalTests(WebDAVElementTestsMixin, TestCase):
"""
Tests for L{CurrentUserPrincipal}.
Modified: CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py 2014-01-16 22:00:09 UTC (rev 12362)
+++ CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py 2014-01-16 22:01:41 UTC (rev 12363)
@@ -7,10 +7,10 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/0a56b418/attachment.html>
More information about the calendarserver-changes
mailing list