pyracmon.marker API documentation
Description: This module provides the abstration mechanism for marker creation used to embed parameters in a query …

# Module `pyracmon.marker`

This module provides the abstration mechanism for marker creation used to embed parameters in a query.

DB-API 2.0 defines some `paramstyle`s and available style depends on DB driver. In addition, some styles are not suitable for query construction in python code. This library adopts unified marker `$_` instead of the styles to make things simple.

Everything in this module is used internally in most cases, thus user does not need to know the detail.

Expand source code

    """
    This module provides the abstration mechanism for marker creation used to embed parameters in a query.

    DB-API 2.0 defines some `paramstyle`s and available style depends on DB driver.
    In addition, some styles are not suitable for query construction in python code.
    This library adopts unified marker `$_` instead of the styles to make things simple.

    Everything in this module is used internally in most cases, thus user does not need to know the detail.
    """
    from typing import Any, Optional, Union

    class Marker:
        """
        Base class to enable unified marker instead of markers defined in DB-API 2.0.

        Each subclass corresponds to a `paramstyle` and implements methods to convert unified marker into its style.
        """
        @classmethod
        def of(cls, paramstyle: str) -> 'Marker':
            """
            Creates an instance for given `paramstyle`.

            Args:
                paramstyle: The name of `paramstyle` defined in DB-API 2.0.
            Returns:
                Created instance.
            """
            if paramstyle == 'qmark':
                return QMarker()
            elif paramstyle == 'numeric':
                return NumericMarker()
            elif paramstyle == 'named':
                return NamedMarker()
            elif paramstyle == 'format':
                return FormatMarker()
            elif paramstyle == 'pyformat':
                return PyformatMarker()
            else:
                raise ValueError(f"Unknown parameter style: {paramstyle}")

        def __call__(self, key: Optional[Union[int, str]] = None) -> str:
            """
            Renders a marker string for the key.

            Each invocation changes internal state of this instance.

            Args:
                key: A key which indicates the parameter. Type of the key depends on the style.
            Returns:
                Marker string.
            """
            if key is None:
                return self.default()
            elif isinstance(key, int) and key > 0:
                return self.indexed(key)
            elif isinstance(key, str) and key != "":
                return self.keyed(key)
            else:
                raise ValueError("Argument of marker invocation must be a positive int or str.")

        def default(self) -> str:
            """
            Generates a string of marker which is not indexed and keyed.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

        def indexed(self, index: int) -> str:
            """
            Generates a string of indexed marker.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

        def keyed(self, key: str) -> str:
            """
            Generates a string of keyed marker.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

        def reset(self):
            """
            Resets the internal state.
            """
            pass

        def params(self, *args: Any, **kwargs: Any) -> Union[list[Any], dict[str, Any]]:
            """
            Generates parameters in the form which is available for query execution.

            This method adjusts the form of given parameters according to the internal state
            which has been changed on each marker generation.

            Args:
                args: Parameters for indexed markers.
                kwargs: Parameters for keyed markers.
            Returns:
                List or dictionary of parameters.
            """
            raise NotImplementedError()

    class ListMarker(Marker):
        def __init__(self, start=0):
            self.index = start
            self.param_keys = []

        def render(self):
            raise NotImplementedError()

        def default(self):
            self.param_keys.append(self.index)
            self.index += 1
            return self.render()

        def indexed(self, index):
            self.param_keys.append(index-1)
            return self.render()

        def keyed(self, key):
            self.param_keys.append(key)
            return self.render()

        def reset(self):
            self.index = 0
            self.param_keys = []

        def params(self, *args, **kwargs):
            def get(k):
                if isinstance(k, int):
                    return args[k]
                else:
                    return kwargs[k]

            return [get(k) for k in self.param_keys]

    class DictMarker(Marker):
        def __init__(self, start=0):
            self.index = start
            self.param_keys = {}

        def render(self, key):
            raise NotImplementedError()

        def new_key(self, index):
            return f"param{index}"

        def default(self):
            key = self.param_keys.setdefault(self.index, self.new_key(self.index+1))
            self.index += 1
            return self.render(key)

        def indexed(self, index):
            key = self.param_keys.setdefault(index-1, self.new_key(index))
            return self.render(key)

        def keyed(self, key):
            self.param_keys[key] = key
            return self.render(key)

        def reset(self):
            self.index = 0
            self.param_keys = {}

        def params(self, *args, **kwargs):
            def get(k, v):
                if isinstance(k, int):
                    return (v, args[k])
                else:
                    return (v, kwargs[k])

            return dict([get(k, v) for k, v in self.param_keys.items()])

    class QMarker(ListMarker):
        """
        This marker renders `?` for any parameter.

        Returns:
            Marker string.
        """
        def render(self) -> str:
            return '?'

    class NumericMarker(ListMarker):
        """
        This marker renders `:x` for the parameter at index `x` (starting from 1).

        Automatic numbering is used when invoked with no `key`, otherwise specified position is selected.
        The index obtained by next automatic numbering is an incremented value of the last obtained index.

        Returns:
            Marker string.
        """
        def render(self) -> str:
            return f":{len(self.param_keys)}"

    class NamedMarker(DictMarker):
        """
        This marker renders `:key` for the parameter bound to `key`.

        Automatic key selection is used when invoked with no `key`, otherwise specified key is selected.
        Each automatic key is in the form of `keyn` where `n` is specified index or its order in generated keys.

        Returns:
            Marker string.
        """
        def render(self, key: str) -> str:
            return f":{key}"

    class FormatMarker(ListMarker):
        """
        This marker renders `%s` for any parameter.

        Returns:
            Marker string.
        """
        def render(self) -> str:
            return '%s'

    class PyformatMarker(DictMarker):
        """
        This marker renders `%(key)s` for the parameter bound to `key`.

        This works similarly to `NamedMarker`.

        Returns:
            Marker string.
        """
        def render(self, key: str) -> str:
            return f"%({key})s"

## Classes

`class DictMarker (start=0)`

  Base class to enable unified marker instead of markers defined in DB-API 2.0.

  Each subclass corresponds to a `paramstyle` and implements methods to convert unified marker into its style.

  Expand source code

      class DictMarker(Marker):
          def __init__(self, start=0):
              self.index = start
              self.param_keys = {}

          def render(self, key):
              raise NotImplementedError()

          def new_key(self, index):
              return f"param{index}"

          def default(self):
              key = self.param_keys.setdefault(self.index, self.new_key(self.index+1))
              self.index += 1
              return self.render(key)

          def indexed(self, index):
              key = self.param_keys.setdefault(index-1, self.new_key(index))
              return self.render(key)

          def keyed(self, key):
              self.param_keys[key] = key
              return self.render(key)

          def reset(self):
              self.index = 0
              self.param_keys = {}

          def params(self, *args, **kwargs):
              def get(k, v):
                  if isinstance(k, int):
                      return (v, args[k])
                  else:
                      return (v, kwargs[k])

              return dict([get(k, v) for k, v in self.param_keys.items()])

  ### Ancestors

  - Marker

  ### Subclasses

  - NamedMarker
  - PyformatMarker

  ### Methods

  `def new_key(self, index)`
    Expand source code

        def new_key(self, index):
            return f"param{index}"

  `def render(self, key)`
    Expand source code

        def render(self, key):
            raise NotImplementedError()

  ### Inherited members

  - `Marker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class FormatMarker (start=0)`

  This marker renders `%s` for any parameter.

  ## Returns

  Marker string.

  Expand source code

      class FormatMarker(ListMarker):
          """
          This marker renders `%s` for any parameter.

          Returns:
              Marker string.
          """
          def render(self) -> str:
              return '%s'

  ### Ancestors

  - ListMarker
  - Marker

  ### Methods

  `def render(self) ‑> str`
    Expand source code

        def render(self) -> str:
            return '%s'

  ### Inherited members

  - `ListMarker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class ListMarker (start=0)`

  Base class to enable unified marker instead of markers defined in DB-API 2.0.

  Each subclass corresponds to a `paramstyle` and implements methods to convert unified marker into its style.

  Expand source code

      class ListMarker(Marker):
          def __init__(self, start=0):
              self.index = start
              self.param_keys = []

          def render(self):
              raise NotImplementedError()

          def default(self):
              self.param_keys.append(self.index)
              self.index += 1
              return self.render()

          def indexed(self, index):
              self.param_keys.append(index-1)
              return self.render()

          def keyed(self, key):
              self.param_keys.append(key)
              return self.render()

          def reset(self):
              self.index = 0
              self.param_keys = []

          def params(self, *args, **kwargs):
              def get(k):
                  if isinstance(k, int):
                      return args[k]
                  else:
                      return kwargs[k]

              return [get(k) for k in self.param_keys]

  ### Ancestors

  - Marker

  ### Subclasses

  - FormatMarker
  - NumericMarker
  - QMarker

  ### Methods

  `def render(self)`
    Expand source code

        def render(self):
            raise NotImplementedError()

  ### Inherited members

  - `Marker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class Marker`

  Base class to enable unified marker instead of markers defined in DB-API 2.0.

  Each subclass corresponds to a `paramstyle` and implements methods to convert unified marker into its style.

  Expand source code

      class Marker:
          """
          Base class to enable unified marker instead of markers defined in DB-API 2.0.

          Each subclass corresponds to a `paramstyle` and implements methods to convert unified marker into its style.
          """
          @classmethod
          def of(cls, paramstyle: str) -> 'Marker':
              """
              Creates an instance for given `paramstyle`.

              Args:
                  paramstyle: The name of `paramstyle` defined in DB-API 2.0.
              Returns:
                  Created instance.
              """
              if paramstyle == 'qmark':
                  return QMarker()
              elif paramstyle == 'numeric':
                  return NumericMarker()
              elif paramstyle == 'named':
                  return NamedMarker()
              elif paramstyle == 'format':
                  return FormatMarker()
              elif paramstyle == 'pyformat':
                  return PyformatMarker()
              else:
                  raise ValueError(f"Unknown parameter style: {paramstyle}")

          def __call__(self, key: Optional[Union[int, str]] = None) -> str:
              """
              Renders a marker string for the key.

              Each invocation changes internal state of this instance.

              Args:
                  key: A key which indicates the parameter. Type of the key depends on the style.
              Returns:
                  Marker string.
              """
              if key is None:
                  return self.default()
              elif isinstance(key, int) and key > 0:
                  return self.indexed(key)
              elif isinstance(key, str) and key != "":
                  return self.keyed(key)
              else:
                  raise ValueError("Argument of marker invocation must be a positive int or str.")

          def default(self) -> str:
              """
              Generates a string of marker which is not indexed and keyed.

              Returns:
                  Marker string.
              """
              raise NotImplementedError()

          def indexed(self, index: int) -> str:
              """
              Generates a string of indexed marker.

              Returns:
                  Marker string.
              """
              raise NotImplementedError()

          def keyed(self, key: str) -> str:
              """
              Generates a string of keyed marker.

              Returns:
                  Marker string.
              """
              raise NotImplementedError()

          def reset(self):
              """
              Resets the internal state.
              """
              pass

          def params(self, *args: Any, **kwargs: Any) -> Union[list[Any], dict[str, Any]]:
              """
              Generates parameters in the form which is available for query execution.

              This method adjusts the form of given parameters according to the internal state
              which has been changed on each marker generation.

              Args:
                  args: Parameters for indexed markers.
                  kwargs: Parameters for keyed markers.
              Returns:
                  List or dictionary of parameters.
              """
              raise NotImplementedError()

  ### Subclasses

  - DictMarker
  - ListMarker

  ### Static methods

  `def of(paramstyle: str) ‑> Marker`

    Creates an instance for given `paramstyle`.

    ## Args

    `paramstyle`
      The name of `paramstyle` defined in DB-API 2.0.

    ## Returns

    Created instance.

    Expand source code

        @classmethod
        def of(cls, paramstyle: str) -> 'Marker':
            """
            Creates an instance for given `paramstyle`.

            Args:
                paramstyle: The name of `paramstyle` defined in DB-API 2.0.
            Returns:
                Created instance.
            """
            if paramstyle == 'qmark':
                return QMarker()
            elif paramstyle == 'numeric':
                return NumericMarker()
            elif paramstyle == 'named':
                return NamedMarker()
            elif paramstyle == 'format':
                return FormatMarker()
            elif paramstyle == 'pyformat':
                return PyformatMarker()
            else:
                raise ValueError(f"Unknown parameter style: {paramstyle}")

  ### Methods

  `def default(self) ‑> str`

    Generates a string of marker which is not indexed and keyed.

    ## Returns

    Marker string.

    Expand source code

        def default(self) -> str:
            """
            Generates a string of marker which is not indexed and keyed.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

  `def indexed(self, index: int) ‑> str`

    Generates a string of indexed marker.

    ## Returns

    Marker string.

    Expand source code

        def indexed(self, index: int) -> str:
            """
            Generates a string of indexed marker.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

  `def keyed(self, key: str) ‑> str`

    Generates a string of keyed marker.

    ## Returns

    Marker string.

    Expand source code

        def keyed(self, key: str) -> str:
            """
            Generates a string of keyed marker.

            Returns:
                Marker string.
            """
            raise NotImplementedError()

  `def params(self, *args: Any, **kwargs: Any) ‑> Union[list[Any], dict[str, Any]]`

    Generates parameters in the form which is available for query execution.

    This method adjusts the form of given parameters according to the internal state which has been changed on each marker generation.

    ## Args

    `args`
      Parameters for indexed markers.
    `kwargs`
      Parameters for keyed markers.

    ## Returns

    List or dictionary of parameters.

    Expand source code

        def params(self, *args: Any, **kwargs: Any) -> Union[list[Any], dict[str, Any]]:
            """
            Generates parameters in the form which is available for query execution.

            This method adjusts the form of given parameters according to the internal state
            which has been changed on each marker generation.

            Args:
                args: Parameters for indexed markers.
                kwargs: Parameters for keyed markers.
            Returns:
                List or dictionary of parameters.
            """
            raise NotImplementedError()

  `def reset(self)`

    Resets the internal state.

    Expand source code

        def reset(self):
            """
            Resets the internal state.
            """
            pass

`class NamedMarker (start=0)`

  This marker renders `:key` for the parameter bound to `key`.

  Automatic key selection is used when invoked with no `key`, otherwise specified key is selected. Each automatic key is in the form of `keyn` where `n` is specified index or its order in generated keys.

  ## Returns

  Marker string.

  Expand source code

      class NamedMarker(DictMarker):
          """
          This marker renders `:key` for the parameter bound to `key`.

          Automatic key selection is used when invoked with no `key`, otherwise specified key is selected.
          Each automatic key is in the form of `keyn` where `n` is specified index or its order in generated keys.

          Returns:
              Marker string.
          """
          def render(self, key: str) -> str:
              return f":{key}"

  ### Ancestors

  - DictMarker
  - Marker

  ### Methods

  `def render(self, key: str) ‑> str`
    Expand source code

        def render(self, key: str) -> str:
            return f":{key}"

  ### Inherited members

  - `DictMarker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class NumericMarker (start=0)`

  This marker renders `:x` for the parameter at index `x` (starting from 1).

  Automatic numbering is used when invoked with no `key`, otherwise specified position is selected. The index obtained by next automatic numbering is an incremented value of the last obtained index.

  ## Returns

  Marker string.

  Expand source code

      class NumericMarker(ListMarker):
          """
          This marker renders `:x` for the parameter at index `x` (starting from 1).

          Automatic numbering is used when invoked with no `key`, otherwise specified position is selected.
          The index obtained by next automatic numbering is an incremented value of the last obtained index.

          Returns:
              Marker string.
          """
          def render(self) -> str:
              return f":{len(self.param_keys)}"

  ### Ancestors

  - ListMarker
  - Marker

  ### Methods

  `def render(self) ‑> str`
    Expand source code

        def render(self) -> str:
            return f":{len(self.param_keys)}"

  ### Inherited members

  - `ListMarker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class PyformatMarker (start=0)`

  This marker renders `%(key)s` for the parameter bound to `key`.

  This works similarly to `NamedMarker`.

  ## Returns

  Marker string.

  Expand source code

      class PyformatMarker(DictMarker):
          """
          This marker renders `%(key)s` for the parameter bound to `key`.

          This works similarly to `NamedMarker`.

          Returns:
              Marker string.
          """
          def render(self, key: str) -> str:
              return f"%({key})s"

  ### Ancestors

  - DictMarker
  - Marker

  ### Methods

  `def render(self, key: str) ‑> str`
    Expand source code

        def render(self, key: str) -> str:
            return f"%({key})s"

  ### Inherited members

  - `DictMarker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`
`class QMarker (start=0)`

  This marker renders `?` for any parameter.

  ## Returns

  Marker string.

  Expand source code

      class QMarker(ListMarker):
          """
          This marker renders `?` for any parameter.

          Returns:
              Marker string.
          """
          def render(self) -> str:
              return '?'

  ### Ancestors

  - ListMarker
  - Marker

  ### Methods

  `def render(self) ‑> str`
    Expand source code

        def render(self) -> str:
            return '?'

  ### Inherited members

  - `ListMarker`:
    - `default`
    - `indexed`
    - `keyed`
    - `of`
    - `params`
    - `reset`