question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Move regular expression compilation to the top of the module in create_from_yaml

See original GitHub issue

I was going through the codebase and was trying to understand it. I landed up at:

https://github.com/kubernetes-client/python/blob/6d64cf67d38337a6fdde1908bdadf047b7118731/kubernetes/utils/create_from_yaml.py#L142-L178

I think we can refactor this function by breaking down it into a couple of nested functions to reduce cognitive complexity and maybe distribute responsibilities.

Furthermore, I have this suggestion and would love to contribute if such a change is acceptable.

upper_followed_by_lower_re = re.compile('(.)([A-Z][a-z]+)')
lower_or_num_followed_by_upper_re = re.compile('([a-z0-9])([A-Z])')

def create_from_yaml_single_item(
        k8s_client, yml_object, verbose=False, **kwargs):

    def get_version_and_group(_api_version):
        _group, _, _version = _api_version.partition("/")
        if _version == "":
            _version = group
            _group = "core"
        return _version, _group

    def clean_group(_group):
        # Take care for the case e.g. api_type is "apiextensions.k8s.io"
        # Only replace the last instance
        _group = "".join(_group.rsplit(".k8s.io", 1))
        # convert group name from DNS subdomain format to
        # python class name convention
        return "".join(word.capitalize() for word in _group.split('.'))

    def clean_kind(_kind):
        # Replace CamelCased action_type into snake_case
        _kind = upper_followed_by_lower_re.sub(r'\1_\2', _kind)
        return lower_or_num_followed_by_upper_re.sub(r'\1_\2', _kind).lower()

    def get_response(_yml_obj, _k8s_api, _kind, **_kwargs):

        def get_namespaced_response(__yml_obj, __k8s_api, __kind, **__kwargs):
            __namespace = __yml_obj["metadata"]["namespace"]
            __kwargs['namespace'] = __namespace
            return getattr(__k8s_api, "create_namespaced_{0}".format(_kind_))(
                body=__yml_obj, **__kwargs)

        def get_non_namespaced_response(__yml_obj, __k8s_apis, __kind, **__kwargs):
            __kwargs.pop('namespace', None)
            return getattr(__k8s_api, "create_{0}".format(__kind))(
                body=__yml_obj, **__kwargs)

        # Expect the user to create namespaced objects more often
        if hasattr(_k8s_api, "create_namespaced_{0}"._format(kind)):
            # Decide which namespace we are going to put the object in,
            # if any
            return get_namespaced_response(_yml_obj, _k8s_api, _kind, **_kwargs)
        return get_non_namespaced_response(_yml_obj, _k8s_api, _kind, **_kwargs)


    def display_message(_kind, _resp, *, _verbose):
        if _verbose:
            _msg = "{0} created.".format(_kind)
            if hasattr(resp, 'status'):
                _msg += " status='{0}'".format(str(_resp.status))
            print(_msg)


    version, group = get_version_and_group(yml_object['apiVersion'])
    group = clean_group(group)

    fcn_to_call = "{0}{1}Api".format(group, version.capitalize())
    k8s_api = getattr(client, fcn_to_call)(k8s_client)
    kind = clean_kind(yml_object['kind'])
    resp = get_response(yml_object, k8s_api, kind, **kwargs)
    display_message(kind, resp, _verbose=verbose)
    return resp

Regarding the code:

  • Prefixed _ in nested function variables so that they are there are lesser chances of facing scoping issues.
  • Move the regular expression pattern to the top of the module as it can hopefully reduce execution time.

I believe a couple of other functions too can be broken down but just wanted to confirm if this is acceptable.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
yliaogcommented, Mar 9, 2021

i’m not sure about the backward incompatibility part, we need the community input on whether it’s worthwhile to make the breaking change. Feel free to send out a PR, we can ask the community to weigh in.

0reactions
abhiabhi94commented, Mar 9, 2021

So, if you agree, i can make a separate pull request for removing the boolean-trap, and it can be merged when a major version is upgraded.

Read more comments on GitHub >

github_iconTop Results From Across the Web

re — Regular expression operations — Python 3.11.1 ...
Source code: Lib/re/ This module provides regular expression matching operations ... as module-level functions and methods on compiled regular expressions.
Read more >
Using regular expressions | Elixir Cookbook - Packt Subscription
We have the Elixir Regex module that is built on top of the Erlang module and ... of regular expressions as alternatives to...
Read more >
re – Regular Expressions - Python Module of the Week
The compile() function converts an expression string into a RegexObject. import re # Pre-compile the patterns regexes = [ re ...
Read more >
When to use re.compile - Stack Overflow
This lets you compile the regex only once versus at each match. ... uncommon to see constants declared at the top of a...
Read more >
Python Tutorial: re Module - How to Write and Match Regular ...
In this Python Programming Tutorial, we will be learning how to read, write, and match regular expressions with the re module.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found