~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to doc/developers/HACKING.txt

  • Committer: John Arbash Meinel
  • Date: 2010-08-30 21:23:49 UTC
  • mto: This revision was merged to the branch mainline in revision 5398.
  • Revision ID: john@arbash-meinel.com-20100830212349-figt9yz2cic6hy68
Remove the 'false' invocation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
359
359
can't fix.
360
360
 
361
361
 
 
362
Getting Input
 
363
=============
 
364
 
 
365
Processing Command Lines
 
366
------------------------
 
367
 
 
368
bzrlib has a standard framework for parsing command lines and calling
 
369
processing routines associated with various commands. See builtins.py
 
370
for numerous examples.
 
371
 
 
372
 
 
373
Standard Parameter Types
 
374
------------------------
 
375
 
 
376
There are some common requirements in the library: some parameters need to be
 
377
unicode safe, some need byte strings, and so on. At the moment we have
 
378
only codified one specific pattern: Parameters that need to be unicode
 
379
should be checked via ``bzrlib.osutils.safe_unicode``. This will coerce the
 
380
input into unicode in a consistent fashion, allowing trivial strings to be
 
381
used for programmer convenience, but not performing unpredictably in the
 
382
presence of different locales.
 
383
 
 
384
 
 
385
Writing Output
 
386
==============
 
387
 
 
388
(The strategy described here is what we want to get to, but it's not
 
389
consistently followed in the code at the moment.)
 
390
 
 
391
bzrlib is intended to be a generically reusable library.  It shouldn't
 
392
write messages to stdout or stderr, because some programs that use it
 
393
might want to display that information through a GUI or some other
 
394
mechanism.
 
395
 
 
396
We can distinguish two types of output from the library:
 
397
 
 
398
 1. Structured data representing the progress or result of an
 
399
    operation.  For example, for a commit command this will be a list
 
400
    of the modified files and the finally committed revision number
 
401
    and id.
 
402
 
 
403
    These should be exposed either through the return code or by calls
 
404
    to a callback parameter.
 
405
 
 
406
    A special case of this is progress indicators for long-lived
 
407
    operations, where the caller should pass a ProgressBar object.
 
408
 
 
409
 2. Unstructured log/debug messages, mostly for the benefit of the
 
410
    developers or users trying to debug problems.  This should always
 
411
    be sent through ``bzrlib.trace`` and Python ``logging``, so that
 
412
    it can be redirected by the client.
 
413
 
 
414
The distinction between the two is a bit subjective, but in general if
 
415
there is any chance that a library would want to see something as
 
416
structured data, we should make it so.
 
417
 
 
418
The policy about how output is presented in the text-mode client
 
419
should be only in the command-line tool.
 
420
 
 
421
 
 
422
Progress and Activity Indications
 
423
---------------------------------
 
424
 
 
425
bzrlib has a way for code to display to the user that stuff is happening
 
426
during a long operation.  There are two particular types: *activity* which
 
427
means that IO is happening on a Transport, and *progress* which means that
 
428
higher-level application work is occurring.  Both are drawn together by
 
429
the `ui_factory`.
 
430
 
 
431
Transport objects are responsible for calling `report_transport_activity`
 
432
when they do IO.
 
433
 
 
434
Progress uses a model/view pattern: application code acts on a
 
435
`ProgressTask` object, which notifies the UI when it needs to be
 
436
displayed.  Progress tasks form a stack.  To create a new progress task on
 
437
top of the stack, call `bzrlib.ui.ui_factory.nested_progress_bar()`, then
 
438
call `update()` on the returned ProgressTask.  It can be updated with just
 
439
a text description, with a numeric count, or with a numeric count and
 
440
expected total count.  If an expected total count is provided the view
 
441
can show the progress moving along towards the expected total.
 
442
 
 
443
The user should call `finish` on the `ProgressTask` when the logical
 
444
operation has finished, so it can be removed from the stack.
 
445
 
 
446
Progress tasks have a complex relationship with generators: it's a very
 
447
good place to use them, but because python2.4 does not allow ``finally``
 
448
blocks in generators it's hard to clean them up properly.  In this case
 
449
it's probably better to have the code calling the generator allocate a
 
450
progress task for its use and then call `finalize` when it's done, which
 
451
will close it if it was not already closed.  The generator should also
 
452
finish the progress task when it exits, because it may otherwise be a long
 
453
time until the finally block runs.
 
454
 
 
455
 
 
456
Message guidelines
 
457
------------------
 
458
 
 
459
When filenames or similar variables are presented inline within a message,
 
460
they should be enclosed in double quotes (ascii 0x22, not chiral unicode
 
461
quotes)::
 
462
 
 
463
  bzr: ERROR: No such file "asdf"
 
464
 
 
465
When we print just a list of filenames there should not be any quoting:
 
466
see `bug 544297`_.
 
467
 
 
468
.. _bug 544297: https://bugs.launchpad.net/bugs/544297
 
469
 
 
470
https://wiki.ubuntu.com/UnitsPolicy provides a good explanation about
 
471
which unit should be used when. Roughly speaking, IEC standard applies
 
472
for base-2 units and SI standard applies for base-10 units:
 
473
 
 
474
* for network bandwidth and disk sizes, use base-10 (Mbits/s, kB/s, GB)
 
475
 
 
476
* for RAM sizes, use base-2 (GiB, TiB)
 
477
 
 
478
 
 
479
 
 
480
Displaying help
 
481
===============
 
482
 
 
483
Bazaar has online help for various topics through ``bzr help COMMAND`` or
 
484
equivalently ``bzr command -h``.  We also have help on command options,
 
485
and on other help topics.  (See ``help_topics.py``.)
 
486
 
 
487
As for python docstrings, the first paragraph should be a single-sentence
 
488
synopsis of the command. These are user-visible and should be prefixed with
 
489
``__doc__ =`` so help works under ``python -OO`` with docstrings stripped.
 
490
 
 
491
The help for options should be one or more proper sentences, starting with
 
492
a capital letter and finishing with a full stop (period).
 
493
 
 
494
All help messages and documentation should have two spaces between
 
495
sentences.
 
496
 
 
497
 
 
498
Handling Errors and Exceptions
 
499
==============================
 
500
 
 
501
Commands should return non-zero when they encounter circumstances that
 
502
the user should really pay attention to - which includes trivial shell
 
503
pipelines.
 
504
 
 
505
Recommended values are:
 
506
 
 
507
    0. OK.
 
508
    1. Conflicts in merge-like operations, or changes are present in
 
509
       diff-like operations.
 
510
    2. Unrepresentable diff changes (i.e. binary files that we cannot show
 
511
       a diff of).
 
512
    3. An error or exception has occurred.
 
513
    4. An internal error occurred (one that shows a traceback.)
 
514
 
 
515
Errors are handled through Python exceptions. Exceptions should be defined
 
516
inside bzrlib.errors, so that we can see the whole tree at a glance.
 
517
 
 
518
We broadly classify errors as either being either internal or not,
 
519
depending on whether ``internal_error`` is set or not.  If we think it's our
 
520
fault, we show a backtrace, an invitation to report the bug, and possibly
 
521
other details.  This is the default for errors that aren't specifically
 
522
recognized as being caused by a user error.  Otherwise we show a briefer
 
523
message, unless -Derror was given.
 
524
 
 
525
Many errors originate as "environmental errors" which are raised by Python
 
526
or builtin libraries -- for example IOError.  These are treated as being
 
527
our fault, unless they're caught in a particular tight scope where we know
 
528
that they indicate a user errors.  For example if the repository format
 
529
is not found, the user probably gave the wrong path or URL.  But if one of
 
530
the files inside the repository is not found, then it's our fault --
 
531
either there's a bug in bzr, or something complicated has gone wrong in
 
532
the environment that means one internal file was deleted.
 
533
 
 
534
Many errors are defined in ``bzrlib/errors.py`` but it's OK for new errors
 
535
to be added near the place where they are used.
 
536
 
 
537
Exceptions are formatted for the user by conversion to a string
 
538
(eventually calling their ``__str__`` method.)  As a convenience the
 
539
``._fmt`` member can be used as a template which will be mapped to the
 
540
error's instance dict.
 
541
 
 
542
New exception classes should be defined when callers might want to catch
 
543
that exception specifically, or when it needs a substantially different
 
544
format string.
 
545
 
 
546
#. If it is something that a caller can recover from, a custom exception
 
547
   is reasonable.
 
548
 
 
549
#. If it is a data consistency issue, using a builtin like
 
550
   ``ValueError``/``TypeError`` is reasonable.
 
551
 
 
552
#. If it is a programmer error (using an api incorrectly)
 
553
   ``AssertionError`` is reasonable.
 
554
 
 
555
#. Otherwise, use ``BzrError`` or ``InternalBzrError``.
 
556
 
 
557
Exception strings should start with a capital letter and should not have a
 
558
final fullstop.  If long, they may contain newlines to break the text.
 
559
 
 
560
 
 
561
 
362
562
Documenting Changes
363
563
===================
364
564