Check-in [1bafafa24d]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implemented the new command.
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1:1bafafa24d16a3cb77a7e31d68b7c07b353fbbf1
User & Date: mvnathan 2014-09-20 09:42:38
Context
2014-09-20
21:48
Since completions logic was being applied in several different places, refactored it into a separate function, which makes the call sites much more compact and readable. check-in: acba4497fc user: mvnathan tags: dev
09:42
Implemented the new command. check-in: 1bafafa24d user: mvnathan tags: dev
08:38
Disallow item creation without any accompanying properties. check-in: 49440f6e1f user: mvnathan tags: dev
Changes

Changes to py/morglib/args.py.

150
151
152
153
154
155
156
157

158
159
160
161
162
163






164
165

166
167
168
169
170
171
172

    @verbatim
        import morglib.args as args

        def parse(argv):
            parser = args.argv_parser(add_help = False)
            parser.add_argument('-h', '--help',
                                action = args.print_help, nargs = 0)

            # etc.
    @endverbatim

    The above will disable argparse's built-in help processing and use
    this one instead.







    '''
    def __call__(self, parser, namespace, values, option_string = None):

        parser.print_help()

#---------------------------- DEBUG SUPPORT -----------------------------

def dump(args):
    '''Dump command-line args to debug log.








|
>






>
>
>
>
>
>


>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

    @verbatim
        import morglib.args as args

        def parse(argv):
            parser = args.argv_parser(add_help = False)
            parser.add_argument('-h', '--help',
                                action = args.print_help,
                                nargs  = 0, default = False)
            # etc.
    @endverbatim

    The above will disable argparse's built-in help processing and use
    this one instead.

    Then, if --help is given on the command-line, the resulting
    argparse.Namespace object will have an attribute named help, which
    will be set to True. Otherwise, the namespace's help attribute will
    be False. Command objects can use this flag to determine whether to
    proceed to command execution or return.

    '''
    def __call__(self, parser, namespace, values, option_string = None):
        setattr(namespace, self.dest, True)
        parser.print_help()

#---------------------------- DEBUG SUPPORT -----------------------------

def dump(args):
    '''Dump command-line args to debug log.

Changes to py/morglib/new.py.

50
51
52
53
54
55
56

57





















58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
        '''Execute new command.

        @param argv (string list) Command-line arguments.
        @param db (morglib.database) Items database.

        '''
        arg = _parse(argv[1:])

        print(arg)






















#------------------------ COMMAND-LINE PARSING --------------------------

def _parse(argv):
    fmt = argparse.RawDescriptionHelpFormatter
    parser = args.argv_parser(description     = _help_before_options(),
                              epilog          = _help_after__options(),
                              prog            = 'new',
                              add_help        = False,
                              formatter_class = fmt)

    parser.add_argument('-h', '--help',
                        action = args.print_help, nargs = 0,
                        help = 'print this help')

    parser.add_argument('-p', '--property',
                        help = 'add a property instead of a task',
                        metavar = 'NAME')
    parser.add_argument('-t', '--property-type',
                        default = 'text', type = _validate_property_type,
................................................................................
                        help = 'range of values property may assume',
                        metavar = 'RANGE')

    parser.add_argument('properties', nargs = argparse.REMAINDER,
                        help = 'property specifications for new task',
                        metavar = 'PROPERTIES')

    arg = parser.parse_args(argv)
    if (arg.property is None and not arg.properties):
        raise args.args_error('cannot create item without properties')
    return arg

def _help_before_options():
    help_text = '''
Use the new command to add items or properties to the Morg database.
Without any options, this command will add a new item to the database,
using the positional arguments as property specifications for the item.

................................................................................

    new -p 'Job Title' -r 'Vice President,Male Gigolo,One Hit Wonder'

Numeric property ranges can also use commas:

    new -p foo -t i 1,3,5,7,9

Additionally, for numeric types, you can use double dots to specify a min
and max values:

    new -p urgency -t r -r 1..-1

Note that we put the min value -1 at the right of the double dot. That's
because it would have confused the new command's command-line parser into
thinking of it as an option -1. But don't worry, Morg's database will do







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|







 







|
<
<
<







 







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
103
104
105
106
107
108
109
110



111
112
113
114
115
116
117
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
        '''Execute new command.

        @param argv (string list) Command-line arguments.
        @param db (morglib.database) Items database.

        '''
        arg = _parse(argv[1:])
        logger.debug("parsed new command's arguments")
        args.dump(arg)
        if (arg.help):
            return

        if (arg.property is None):
            logger.info('building properties list for new item')
            properties = {}
            for p in arg.properties:
                s = p.split('=')
                if (len(s) < 2):
                    raise args.args_error('property {} has no value'.
                                          format(s[0]))
                if (len(s) > 2):
                    raise args.args_error('property {} has multiple values'.
                                          format(s[0]))
                properties[s[0].strip()] = s[1].strip()
            db.add_item(properties)

        else:
            n, t, r = arg.property, arg.property_type, arg.property_range
            logger.debug('creating new property ({}, {}, {})'.format(n, t, r))
            db.add_property(n, t, r)

#------------------------ COMMAND-LINE PARSING --------------------------

def _parse(argv):
    fmt = argparse.RawDescriptionHelpFormatter
    parser = args.argv_parser(description     = _help_before_options(),
                              epilog          = _help_after__options(),
                              prog            = 'new',
                              add_help        = False,
                              formatter_class = fmt)

    parser.add_argument('-h', '--help',
                        action = args.print_help, nargs = 0, default = False,
                        help = 'print this help')

    parser.add_argument('-p', '--property',
                        help = 'add a property instead of a task',
                        metavar = 'NAME')
    parser.add_argument('-t', '--property-type',
                        default = 'text', type = _validate_property_type,
................................................................................
                        help = 'range of values property may assume',
                        metavar = 'RANGE')

    parser.add_argument('properties', nargs = argparse.REMAINDER,
                        help = 'property specifications for new task',
                        metavar = 'PROPERTIES')

    return parser.parse_args(argv)




def _help_before_options():
    help_text = '''
Use the new command to add items or properties to the Morg database.
Without any options, this command will add a new item to the database,
using the positional arguments as property specifications for the item.

................................................................................

    new -p 'Job Title' -r 'Vice President,Male Gigolo,One Hit Wonder'

Numeric property ranges can also use commas:

    new -p foo -t i 1,3,5,7,9

Additionally, for numeric types, you can use double dots to specify min
and max values:

    new -p urgency -t r -r 1..-1

Note that we put the min value -1 at the right of the double dot. That's
because it would have confused the new command's command-line parser into
thinking of it as an option -1. But don't worry, Morg's database will do

Changes to wiki/todo.wiki.

23
24
25
26
27
28
29


30
31
32
33
34
35
  *  Implement a watermark class to ease verification and "Morgification."
  *  The watermark table should be created and populated in a transaction.
  *  Update doc strings to reflect recent changes about the watermark.
  *  Pass database to all commands' <tt>__call__</tt> method.
  *  Generalize Morg so it isn't necessarily task-centric.
  *  Implement <tt>morglib.database.add_item()</tt>.
  *  Implement <tt>new</tt> command-line processing.



<h2>PENDING</h2>

  *  Hook up <tt>new</tt> command to <tt>add_item()</tt>.
  *  Hook up <tt>new</tt> command to <tt>add_property()</tt>.
  *  Add some user documentation.







>
>



|
<

23
24
25
26
27
28
29
30
31
32
33
34
35

36
  *  Implement a watermark class to ease verification and "Morgification."
  *  The watermark table should be created and populated in a transaction.
  *  Update doc strings to reflect recent changes about the watermark.
  *  Pass database to all commands' <tt>__call__</tt> method.
  *  Generalize Morg so it isn't necessarily task-centric.
  *  Implement <tt>morglib.database.add_item()</tt>.
  *  Implement <tt>new</tt> command-line processing.
  *  Hook up <tt>new</tt> command to <tt>add_item()</tt>.
  *  Hook up <tt>new</tt> command to <tt>add_property()</tt>.

<h2>PENDING</h2>

  *  Refactor completions code and exception into utils module.

  *  Add some user documentation.