If you are interested in contributing to the Calendar and Contacts Server project, please read this document.
The Calendar and Contacts Server began in 1996 -- an open source project sponsored and hosted by Apple Inc. (http://www.apple.com/). The project is now hosted at GitHub, and although it lives within the "apple" namespace it's still a true open-source project under an Apache license. Contributions from other developers are welcome, and, as with all open development projects, may lead to "commit access" and a voice in the future of the project.
The community exists mainly through mailing lists and a GitHub repository. To participate, go to:
https://www.calendarserver.org/MailingLists.html
and join the appropriate mailing lists. We also use IRC, as described here:
https://www.calendarserver.org/IRC.html
There are many ways to join the project. One may write code, test the software and file bugs, write documentation, etc.
The issue tracking database is here:
https://github.com/apple/ccs-calendarserver/issues
To help manage the issues database, read over the issue summaries, looking and testing for issues that are either invalid, or are duplicates of other issues. Both kinds are very common, the first because bugs often get unknowingly fixed as side effects of other changes in the code, and the second because people sometimes file an issue without noticing that it has already been reported. If you are not sure about an issue, post a question to
calendarserver-dev@lists.macosforge.org.
Before filing bugs, please take a moment to perform a quick search to see if someone else has already filed your bug. In that case, add a comment to the existing bug if appropriate and monitor it, rather than filing a duplicate.
The source code to the Calendar and Contacts Server is available via Git at this repository URL:
https://github.com/apple/ccs-calendarserver.git
A rough guide to the source tree:
doc/
- User and developer documentation, including relevant protocol specifications and extensions.bin/
- Executable programs.conf/
- Configuration files.calendarserver/
- Source code for the Calendar and Contacts Servertwistedcaldav/
- Source code for CalDAV librarytwisted/
- Files required to set up the Calendar and Contacts Server as a Twisted service. Twisted (http://twistedmatrix.com/) is a networking framework upon which the Calendar and Contacts Server is built.locales/
- Localization files.contrib/
- Extra stuff that works with the Calendar and Contacts Server, or that helps integrate with other software (including operating systems), but that the Calendar and Contacts Server does not depend on.support/
- Support files of possible use to developers.
The vast majority of the Calendar and Contacts Server is written in the Python programming language. When writing Python code for the Calendar and Contacts Server, please observe the following conventions.
Please note that all of our code at present does not follow these standards, but that does not mean that one shouldn't bother to do so. On the contrary, code changes that do nothing but reformat code to comply with these standards are welcome, and code changes that do not conform to these standards are discouraged.
We require Python 2.6 or higher. It therefore is OK to write code that does not work with Python versions older than 2.6.
Read PEP-8:
https://www.python.org/dev/peps/pep-0008/
For the most part, our code should follow PEP-8, with a few exceptions and a few additions. It is also useful to review the Twisted Coding Standard, from which we borrow some standards, though we don't strictly follow it:
https://twistedmatrix.com/documents/current/core/development/policy/coding-standard.html
Key items to follow, and specifics:
- Indent level is 4 spaces.
- Never indent code with tabs. Always use spaces.
PEP-8 items we do not follow:
PEP-8 recommends using a backslash to break long lines up:
if width == 0 and height == 0 and \ color == 'red' and emphasis == 'strong' or \ highlight > 100: raise ValueError("sorry, you lose")Don't do that, it's gross, and the indentation for the
raise
line gets confusing. Use parentheses:if ( width == 0 and height == 0 and color == "red" and emphasis == "strong" or highlight > 100 ): raise ValueError("sorry, you lose")Just don't do it the way PEP-8 suggests:
if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so")Because that's just silly.
Additions:
Close parentheses and brackets such as
()
,[]
and{}
at the same indent level as the line in which you opened it:launchAtTarget( target="David", object=PaperWad( message="Yo!", crumpleFactor=0.7, ), speed=0.4, )Long lines are often due to long strings. Try to break strings up into multiple lines:
processString( "This is a very long string with a lot of text. " "Fortunately, it is easy to break it up into parts " "like this." )Similarly, callables that take many arguments can be broken up into multiple lines, as in the
launchAtTarget()
example above.Breaking generator expressions and list comprehensions into multiple lines can improve readability. For example:
myStuff = ( item.obtainUsefulValue() for item in someDataStore if item.owner() == me )Import symbols (especially class names) from modules instead of importing modules and referencing the symbol via the module unless it doesn't make sense to do so. For example:
from subprocess import Popen process = Popen(...)Instead of:
import subprocess process = subprocess.Popen(...)This makes code shorter and makes it easier to replace one implementation with another.
All files should have an
__all__
specification. Put them at the top of the file, before imports (PEP-8 puts them at the top, but after the imports), so you can see what the public symbols are for a file right at the top.It is more important that symbol names are meaningful than it is that they be concise.
x
is rarely an appropriate name for a variable. Avoid contractions:transmogrifierStatus
is more useful to the reader thantrmgStat
.A deferred that will be immediately returned may be called
d
:d = doThisAndThat() d.addCallback(onResult) d.addErrback(onError) return dDo not use
deferredGenerator
. UseinlineCallbacks
instead.That said, avoid using
inlineCallbacks
when chaining deferreds is straightforward, as they are more expensive. UseinlineCallbacks
when necessary for keeping code maintainable, such as when creating serialized deferreds in a for loop.
_
may be used to denote unused callback arguments:def onCompletion(_): # Don't care about result of doThisAndThat() in here; # we only care that it has completed. doNextThing() d = doThisAndThat() d.addCallback(onCompletion) return dDo not prefix symbols with
_
unless they might otherwise be exposed as a public symbol: a private method name should begin with_
, but a locally scoped variable should not, as there is no danger of it being exposed. Locally scoped variables are already private.Per twisted convention, use camel-case (
fuzzyWidget
,doThisAndThat()
) for symbol names instead of using underscores (fuzzy_widget
,do_this_and_that()
).Use of underscores is reserved for implied dispatching and the like (eg.
http_FOO()
). See the Twisted Coding Standard for details.Do not use
%
-formatting:error = "Unexpected value: %s" % (value,)Use PEP-3101 formatting instead:
error = "Unexpected value: {value}".format(value=value)If you must use
%
-formatting for some reason, always use a tuple as the format argument, even when only one value is being provided:error = "Unexpected value: %s" % (value,)Never use the non-tuple form:
error = "Unexpected value: %s" % valueWhich is allowed in Python, but results in a programming error if
type(value) is tuple and len(value) != 1
.Don't use a trailing
,
at the end of a tuple if it's on one line:numbers = (1,2,3,) # No numbers = (1,2,3) # YesThe trailing comma is desirable on multiple lines, though, as that makes re-ordering items easy, and avoids a diff on the last line when adding another:
strings = ( "This is a string.", "And so is this one.", "And here is yet another string.", )Docstrings are important. All public symbols (anything declared in
__all__
) must have a correct docstring. The scriptdocs/Developer/gendocs
will generate the API documentation usingpydoctor
. See thepydoctor
documentation for details on the formatting:Note: existing docstrings need a complete review.
Use PEP-257 as a guideline for docstrings.
Begin all multi-line docstrings with 3 double quotes and a newline:
def doThisAndThat(...): """ Do this, and that. ... """
If a callable is going to return a Deferred some of the time, it should return a deferred all of the time. Return
succeed(value)
instead ofvalue
if necessary. This avoids forcing the caller to check as to whether the value is a deferred or not (eg. by usingmaybeDeferred()
), which is both annoying to code and potentially expensive at runtime.Be proactive about closing files and file-like objects.
For a lot of Python software, letting Python close the stream for you works fine, but in a long-lived server that's processing many data streams at a time, it is important to close them as soon as possible.
On some platforms (eg. Windows), deleting a file will fail if the file is still open. By leaving it up to Python to decide when to close a file, you may find yourself being unable to reliably delete it.
The most reliable way to ensure that a stream is closed is to put the call to
close()
in afinally
block:stream = file(somePath) try: ... do something with stream ... finally: stream.close()
Be sure that all of the units tests pass before you commit new code. Code that breaks units tests may be reverted without further discussion; it is up to the committer to fix the problem and try again.
Note that repeatedly committing code that breaks units tests presents a possible time sink for other developers, and is not looked upon favorably.
Units tests can be run rather easily by executing the ./bin/test
script
at the top of the Calendar and Contacts Server source tree. By
default, it will run all of the Calendar and Contacts Server tests
followed by all of the Twisted tests. You can run specific tests by
specifying them as arguments like this:
./bin/test twistedcaldav.static
All non-trivial public callables must have unit tests. (Note we don't don't totally comply with this rule; that's a problem we'd like to fix.) All other callables should have unit tests.
Units tests are written using the twisted.trial
framework. Test
module names should start with test_
. Twisted has some tips on
writing tests here:
https://twistedmatrix.com/documents/current/core/howto/testing.html
https://twistedmatrix.com/documents/current/core/development/policy/test-standard.html
We also use CalDAVTester (which is a companion to the Calendar and Contacts Server), which performs more "black box"-type testing against the server to ensure compliance with the CalDAV protocol. That requires running the server with a test configuration and then running CalDAVTester against it. Information about CalDAVTester is available here:
https://github.com/apple/ccs-caldavtester
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。