PY-11855 Run manage.py task improvements
[idea/community.git] / python / helpers / pycharm / _django_obtainer_core.py
1 # coding=utf-8
2 """
3 TODO: Support real help (from show_help()), not only help text
4 This module exports information about manage commands and options from django to PyCharm.
5 Information is provided in XML (to prevent encoding troubles and simplify deserialization on java side).
6 It does not have schema (yet!) but here is XML format it uses.
7
8 <commandInfo-array> -- root
9 <commandInfo args="args description" help="human readable text" name="command name"> -- info about command
10 <option help="option help" numberOfArgs="number of values (nargs)" type="option type: Option.TYPES"> -- one entry for each option
11 <longNames>--each-for-one-long-opt-name</longNames>
12 <shortNames>-each-for-one-short-name</shortNames>
13 </option>
14 </commandInfo>
15 </commandInfo-array>
16
17
18
19 """
20 from distutils.version import StrictVersion
21 from xml.dom import minidom
22 from xml.dom.minidom import Element
23 import django
24 import _django_obtainer_optparse
25
26 __author__ = 'Ilya.Kazakevich'
27
28
29 class XmlDumper(object):
30     """"
31     Creates an API to generate XML provided in this package.
32     How to use:
33     * dumper.start_command(..)
34     * dumper.add_command_option(..) # optional
35     * dumper.close_command()
36     * print(dumper.xml)
37
38     """
39
40     __command_info_tag = "commandInfo"  # Name of main tag
41
42     def __init__(self):
43         self.__document = minidom.Document()
44         self.__root = self.__document.createElement("{0}-array".format(XmlDumper.__command_info_tag))
45         self.__document.appendChild(self.__root)
46         self.__command_element = None
47
48     def __create_text_array(self, parent, tag_name, values):
49         """
50         Creates array of text elements and adds them to parent
51
52         :type parent Element
53         :type tag_name str
54         :type values list of str
55
56         :param parent destination to add new elements
57         :param tag_name name tag to create to hold text
58         :param values list of values to add
59
60         """
61         for value in values:
62             tag = self.__document.createElement(tag_name)
63             text = self.__document.createTextNode(value)
64             tag.appendChild(text)
65             parent.appendChild(tag)
66
67     def start_command(self, command_name, command_help_text, command_args_text):
68         """
69         Starts manage command
70
71         :param command_name: command name
72         :param command_help_text: command help
73         :param command_args_text: command text for args
74
75
76         """
77         assert not bool(self.__command_element), "Already in command"
78         self.__command_element = self.__document.createElement(XmlDumper.__command_info_tag)
79         self.__command_element.setAttribute("name", command_name)
80         self.__command_element.setAttribute("help", command_help_text)
81         self.__command_element.setAttribute("args", command_args_text)
82         self.__root.appendChild(self.__command_element)
83
84     def add_command_option(self, opt_type, choices, long_opt_names, short_opt_names, help_text, num_of_args):
85         """
86         Adds command option
87
88         :param opt_type: "string", "int", "long", "float", "complex", "choice"
89         :param choices: list of choices for "choice" type
90         :param long_opt_names:  list of long opt names
91         :param short_opt_names: list of short opt names
92         :param help_text: help text
93         :param num_of_args: number of arguments
94
95         :type opt_type str
96         :type choices list of string
97         :type long_opt_names list of str
98         :type short_opt_names list of str
99         :type help_text str
100         :type num_of_args int
101         """
102         assert isinstance(self.__command_element, Element), "Add option in command only"
103         option = self.__document.createElement("option")
104         option.setAttribute("type", opt_type)
105
106         if choices:
107             self.__create_text_array(option, "choices", choices)
108         if long_opt_names:
109             self.__create_text_array(option, "longNames", long_opt_names)
110         if short_opt_names:
111             self.__create_text_array(option, "shortNames", short_opt_names)
112
113         option.setAttribute("help", help_text)
114         if num_of_args:
115             option.setAttribute("numberOfArgs", str(num_of_args))
116         self.__command_element.appendChild(option)
117
118     def close_command(self):
119         """
120         Closes currently opened command
121         """
122         assert bool(self.__command_element), "No command to close"
123         self.__command_element = None
124         pass
125
126     @property
127     def xml(self):
128         """
129
130         :return: current commands as XML as described in package
131         :rtype str
132         """
133         return self.__document.toprettyxml()