text: import json
  
  from django import forms
  from django.conf import settings
  from django.contrib.postgres.forms import SimpleArrayField
  
  from utilities.choices import ColorChoices
  from .utils import add_blank_choice, parse_numeric_range
  
  __all__ = (
      'APISelect',
      'APISelectMultiple',
      'BulkEditNullBooleanSelect',
      'ColorSelect',
      'ContentTypeSelect',
      'DatePicker',
      'DateTimePicker',
      'NumericArrayField',
      'SelectWithDisabled',
      'SelectWithPK',
      'SlugWidget',
      'SmallTextarea',
      'StaticSelect2',
      'StaticSelect2Multiple',
      'TimePicker',
  )
  
  
  class SmallTextarea(forms.Textarea):
      """
      Subclass used for rendering a smaller textarea element.
      """
      pass
  
  
  class SlugWidget(forms.TextInput):
      """
      Subclass TextInput and add a slug regeneration button next to the form field.
      """
      template_name = 'widgets/sluginput.html'
  
  
  class ColorSelect(forms.Select):
      """
      Extends the built-in Select widget to colorize each <option>.
      """
      option_template_name = 'widgets/colorselect_option.html'
  
      def __init__(self, *args, **kwargs):
          kwargs['choices'] = add_blank_choice(ColorChoices)
          super().__init__(*args, **kwargs)
          self.attrs['class'] = 'netbox-select2-color-picker'
  
  
  class BulkEditNullBooleanSelect(forms.NullBooleanSelect):
      """
      A Select widget for NullBooleanFields
      """
  
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          # Override the built-in choice labels
          self.choices = (
              ('1', '---------'),
              ('2', 'Yes'),
              ('3', 'No'),
          )
          self.attrs['class'] = 'netbox-select2-static'
  
  
  class SelectWithDisabled(forms.Select):
      """
      Modified the stock Select widget to accept choices using a dict() for a label. The dict for each option must include
      'label' (string) and 'disabled' (boolean).
      """
      option_template_name = 'widgets/selectwithdisabled_option.html'
  
  
  class StaticSelect2(SelectWithDisabled):
      """
      A static <select> form widget using the Select2 library.
      """
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.attrs['class'] = 'netbox-select2-static'
  
  
  class StaticSelect2Multiple(StaticSelect2, forms.SelectMultiple):
  
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.attrs['data-multiple'] = 1
  
  
  class SelectWithPK(StaticSelect2):
      """
      Include the primary key of each option in the option label (e.g. "Router7 (4721)").
      """
      option_template_name = 'widgets/select_option_with_pk.html'
  
  
  class ContentTypeSelect(StaticSelect2):
      """
      Appends an `api-value` attribute equal to the slugified model name for each ContentType. For example:
          <option value="37" api-value="console-server-port">console server port</option>
      This attribute can be used to reference the relevant API endpoint for a particular ContentType.
      """
      option_template_name = 'widgets/select_contenttype.html'
  
  
  class NumericArrayField(SimpleArrayField):
  
      def to_python(self, value):
          value = ','.join([str(n) for n in parse_numeric_range(value)])
          return super().to_python(value)
  
  
  class APISelect(SelectWithDisabled):
      """
      A select widget populated via an API call
  
      :param api_url: API endpoint URL. Required if not set automatically by the parent field.
      """
      def __init__(self, api_url=None, full=False, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.attrs['class'] = 'netbox-select2-api'
          if api_url:
              self.attrs['data-url'] = '/{}{}'.format(settings.BASE_PATH, api_url.lstrip('/'))  # Inject BASE_PATH
  
      def add_query_param(self, name, value):
          """
          Add details for an additional query param in the form of a data-* JSON-encoded list attribute.
  
          :param name: The name of the query param
          :param value: The value of the query param
          """
          key = f'data-query-param-{name}'
  
          values = json.loads(self.attrs.get(key, '[]'))
          if type(value) is list:
              values.extend([str(v) for v in value])
          else:
              values.append(str(value))
  
          self.attrs[key] = json.dumps(values)
  
  
  class APISelectMultiple(APISelect, forms.SelectMultiple):
  
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.attrs['data-multiple'] = 1
  
  
  class DatePicker(forms.TextInput):
      """
      Date picker using Flatpickr.
      """
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
          self.attrs['class'] = 'date-picker'
          self.attrs['placeholder'] = 'YYYY-MM-DD'
  
  
  class DateTimePicker(forms.TextInput):
      """
      DateTime picker using Flatpickr.
      """
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
          self.attrs['class'] = 'datetime-picker'
          self.attrs['placeholder'] = 'YYYY-MM-DD hh:mm:ss'
  
  
  class TimePicker(forms.TextInput):
      """
      Time picker using Flatpickr.
      """
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
          self.attrs['class'] = 'time-picker'
          self.attrs['placeholder'] = 'hh:mm:ss'
  