<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def search(self, pkg_name=None, search_carts=False, query='/content/units/rpm/search/'):
 """ search for a package stored in a pulp repo `pkg_name` - substring in the name of the package `search_carts` - whether or not to return carts that include the listed package """

        # this data block is... yeah. searching in pulp v2 is painful
        #
        # https://pulp-dev-guide.readthedocs.org/en/latest/rest-api/content/retrieval.html#search-for-units
        # https://pulp-dev-guide.readthedocs.org/en/latest/rest-api/conventions/criteria.html#search-criteria
        #
        # those are the API docs for searching
        data = {
                    'criteria': {
                        'filters': {'filename': {'$regex': ".*%s.*" % pkg_name}},
                        'sort': [['name', 'ascending']],
                        'fields': ['name', 'description', 'version', 'release', 'arch', 'filename']
                    },
                    'include_repos': 'true'
                }
        repos = []

        juicer.utils.Log.log_info('Packages:')

        for env in self.args.environment:
            juicer.utils.Log.log_debug("Querying %s server" % env)
            _r = self.connectors[env].post(query, data)

            if not _r.status_code == Constants.PULP_POST_OK:
                juicer.utils.Log.log_debug("Expected PULP_POST_OK, got %s", _r.status_code)
                _r.raise_for_status()

            juicer.utils.Log.log_info('%s:' % str.upper(env))

            pkg_list = juicer.utils.load_json_str(_r.content)

            for package in pkg_list:
                # if the package is in a repo, show a link to the package in said repo
                # otherwise, show nothing
                if len(package['repository_memberships']) > 0:
                    target = package['repository_memberships'][0]

                    _r = self.connectors[env].get('/repositories/%s/' % target)
                    if not _r.status_code == Constants.PULP_GET_OK:
                        raise JuicerPulpError("%s was not found as a repoid. A %s status code was returned" %
                                (target, _r.status_code))
                    repo = juicer.utils.load_json_str(_r.content)['display_name']
                    repos.append(repo)

                    link = juicer.utils.remote_url(self.connectors[env], env, repo, package['filename'])
                else:
                    link = ''

                juicer.utils.Log.log_info('%s\t%s\t%s\t%s' % (package['name'], package['version'], package['release'], link))

        if search_carts:
            # if the package is in a cart, show the cart name
            juicer.utils.Log.log_info('\nCarts:')

            for env in self.args.environment:
                carts = juicer.utils.search_carts(env, pkg_name, repos)
                for cart in carts:
                    juicer.utils.Log.log_info(cart['_id'])