URL: https://github.com/freeipa/freeipa/pull/1584 Author: tiran Title: #1584: [Backport][ipa-4-6] Generate same API.txt under Python 2 and 3 Action: opened
PR body: """ This PR was opened automatically because PR #1580 was pushed to master and backport to ipa-4-6 is required. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/1584/head:pr1584 git checkout pr1584
From b62729e37b7c7b3f16ca04c130a64758e2d06151 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Wed, 14 Feb 2018 16:59:50 +0100 Subject: [PATCH 1/2] Generate same API.txt under Python 2 and 3 Use Python 3's reprlib with customizations to create same API.txt under Python 2 and 3. Some plugins have been slightly altered to use stable sorting for dynamically created parameter lists. Signed-off-by: Christian Heimes <chei...@redhat.com> --- API.txt | 8 +++--- ipalib/output.py | 3 ++- ipalib/parameters.py | 9 ++++--- ipalib/util.py | 38 ++++++++++++++++++++++++++ ipaserver/plugins/idrange.py | 19 ++++++------- ipaserver/plugins/migration.py | 32 +++++++++++----------- ipaserver/plugins/trust.py | 54 ++++++++++++++++++++----------------- ipatests/test_ipalib/test_output.py | 8 ++++-- 8 files changed, 111 insertions(+), 60 deletions(-) diff --git a/API.txt b/API.txt index 0526d5a902..05dec4475c 100644 --- a/API.txt +++ b/API.txt @@ -2973,7 +2973,7 @@ option: Int('ipabaserid?', cli_name='rid_base') option: Int('ipaidrangesize', cli_name='range_size') option: Str('ipanttrusteddomainname?', cli_name='dom_name') option: Str('ipanttrusteddomainsid?', cli_name='dom_sid') -option: StrEnum('iparangetype?', cli_name='type', values=[u'ipa-ad-trust-posix', u'ipa-ad-trust', u'ipa-local']) +option: StrEnum('iparangetype?', cli_name='type', values=[u'ipa-ad-trust', u'ipa-ad-trust-posix', u'ipa-local']) option: Int('ipasecondarybaserid?', cli_name='secondary_rid_base') option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Str('setattr*', cli_name='setattr') @@ -2998,7 +2998,7 @@ option: Int('ipabaseid?', autofill=False, cli_name='base_id') option: Int('ipabaserid?', autofill=False, cli_name='rid_base') option: Int('ipaidrangesize?', autofill=False, cli_name='range_size') option: Str('ipanttrusteddomainsid?', autofill=False, cli_name='dom_sid') -option: StrEnum('iparangetype?', autofill=False, cli_name='type', values=[u'ipa-ad-trust-posix', u'ipa-ad-trust', u'ipa-local']) +option: StrEnum('iparangetype?', autofill=False, cli_name='type', values=[u'ipa-ad-trust', u'ipa-ad-trust-posix', u'ipa-local']) option: Int('ipasecondarybaserid?', autofill=False, cli_name='secondary_rid_base') option: Flag('pkey_only?', autofill=True, default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False) @@ -3255,7 +3255,7 @@ option: Str('groupignoreobjectclass*', autofill=True, cli_name='group_ignore_obj option: Str('groupobjectclass+', autofill=True, cli_name='group_objectclass', default=[u'groupOfUniqueNames', u'groupOfNames']) option: Flag('groupoverwritegid', autofill=True, cli_name='group_overwrite_gid', default=False) option: StrEnum('schema?', autofill=True, cli_name='schema', default=u'RFC2307bis', values=[u'RFC2307bis', u'RFC2307']) -option: StrEnum('scope', autofill=True, cli_name='scope', default=u'onelevel', values=[u'base', u'subtree', u'onelevel']) +option: StrEnum('scope', autofill=True, cli_name='scope', default=u'onelevel', values=[u'base', u'onelevel', u'subtree']) option: Bool('use_def_group?', autofill=True, cli_name='use_default_group', default=True) option: DNParam('usercontainer', autofill=True, cli_name='user_container', default=ipapython.dn.DN('ou=people')) option: Str('userignoreattribute*', autofill=True, cli_name='user_ignore_attribute', default=[]) @@ -5721,7 +5721,7 @@ option: Int('base_id?', cli_name='base_id') option: Bool('bidirectional?', cli_name='two_way', default=False) option: Bool('external?', cli_name='external', default=False) option: Int('range_size?', cli_name='range_size') -option: StrEnum('range_type?', cli_name='range_type', values=[u'ipa-ad-trust-posix', u'ipa-ad-trust']) +option: StrEnum('range_type?', cli_name='range_type', values=[u'ipa-ad-trust', u'ipa-ad-trust-posix']) option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Str('realm_admin?', cli_name='admin') option: Password('realm_passwd?', cli_name='password', confirm=False) diff --git a/ipalib/output.py b/ipalib/output.py index b104584631..afcbefa110 100644 --- a/ipalib/output.py +++ b/ipalib/output.py @@ -25,6 +25,7 @@ from ipalib.plugable import ReadOnly, lock from ipalib.capabilities import client_has_capability from ipalib.text import _ +from ipalib.util import apirepr if six.PY3: unicode = str @@ -98,7 +99,7 @@ def __repr_iter(self): if not value: continue if isinstance(value, tuple): - value = repr(list(value)) + value = apirepr(list(value)) else: value = repr(value) yield '%s=%s' % (key, value) diff --git a/ipalib/parameters.py b/ipalib/parameters.py index ead56c018e..902ae3401b 100644 --- a/ipalib/parameters.py +++ b/ipalib/parameters.py @@ -123,7 +123,7 @@ from ipalib.util import json_serialize, validate_idna_domain from ipalib.x509 import ( load_der_x509_certificate, IPACertificate, default_backend) -from ipalib.util import strip_csr_header +from ipalib.util import strip_csr_header, apirepr from ipapython import kerberos from ipapython.dn import DN from ipapython.dnsutil import DNSName @@ -600,9 +600,12 @@ def __repr_iter(self): elif isinstance(value, six.integer_types): value = str(value) elif isinstance(value, (tuple, set, frozenset)): - value = repr(list(value)) - else: + value = apirepr(list(value)) + elif key == 'cli_name': + # always represented as native string value = repr(value) + else: + value = apirepr(value) yield '%s=%s' % (key, value) def __call__(self, value, **kw): diff --git a/ipalib/util.py b/ipalib/util.py index f154c0b10d..ebf6eb3faf 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -66,6 +66,11 @@ from ipapython.dnsutil import resolve_ip_addresses from ipapython.admintool import ScriptError +if sys.version_info >= (3, 2): + import reprlib # pylint: disable=import-error +else: + reprlib = None + if six.PY3: unicode = str @@ -1206,3 +1211,36 @@ def open_in_pager(data): pager_process.communicate() except IOError: pass + + +if reprlib is not None: + class APIRepr(reprlib.Repr): + builtin_types = { + bool, int, float, + str, bytes, + dict, tuple, list, set, frozenset, + type(None), + } + + def __init__(self): + super(APIRepr, self).__init__() + # no limitation + for k, v in self.__dict__.items(): + if isinstance(v, int): + setattr(self, k, sys.maxsize) + + def repr_str(self, x, level): + """Output with u'' prefix""" + return 'u' + repr(x) + + def repr_type(self, x, level): + if x is str: + return "<type 'unicode'>" + if x in self.builtin_types: + return "<type '{}'>".format(x.__name__) + else: + return repr(x) + + apirepr = APIRepr().repr +else: + apirepr = repr diff --git a/ipaserver/plugins/idrange.py b/ipaserver/plugins/idrange.py index b67ed31082..6b37d9d708 100644 --- a/ipaserver/plugins/idrange.py +++ b/ipaserver/plugins/idrange.py @@ -239,18 +239,19 @@ class idrange(LDAPObject): cli_name='dom_name', flags=('no_search', 'virtual_attribute', 'no_update'), label=_('Name of the trusted domain'), - ), + ), StrEnum('iparangetype?', - label=_('Range type'), - cli_name='type', - doc=(_('ID range type, one of {vals}' - .format(vals=', '.join(range_types.keys())))), - values=tuple(range_types.keys()), - flags=['no_update'], - ) + label=_('Range type'), + cli_name='type', + doc=(_('ID range type, one of {vals}' + .format(vals=', '.join(sorted(range_types))))), + values=sorted(range_types), + flags=['no_update'], + ) ) - def handle_iparangetype(self, entry_attrs, options, keep_objectclass=False): + def handle_iparangetype(self, entry_attrs, options, + keep_objectclass=False): if not any((options.get('pkey_only', False), options.get('raw', False))): range_type = entry_attrs['iparangetype'][0] diff --git a/ipaserver/plugins/migration.py b/ipaserver/plugins/migration.py index b89fba0d76..724c704ca5 100644 --- a/ipaserver/plugins/migration.py +++ b/ipaserver/plugins/migration.py @@ -632,24 +632,24 @@ class migrate_ds(Command): doc=_('Load CA certificate of LDAP server from FILE'), default=None, noextrawhitespace=False, - ), + ), Bool('use_def_group?', - cli_name='use_default_group', - label=_('Add to default group'), - doc=_('Add migrated users without a group to a default group ' - '(default: true)'), - default=True, - autofill=True, - ), + cli_name='use_default_group', + label=_('Add to default group'), + doc=_('Add migrated users without a group to a default group ' + '(default: true)'), + default=True, + autofill=True, + ), StrEnum('scope', - cli_name='scope', - label=_('Search scope'), - doc=_('LDAP search scope for users and groups: base, onelevel, or ' - 'subtree. Defaults to onelevel'), - values=tuple(_supported_scopes.keys()), - default=_default_scope, - autofill=True, - ), + cli_name='scope', + label=_('Search scope'), + doc=_('LDAP search scope for users and groups: base, ' + 'onelevel, or subtree. Defaults to onelevel'), + values=sorted(_supported_scopes), + default=_default_scope, + autofill=True, + ), ) has_output = ( diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py index 978738e20a..91cd1387ce 100644 --- a/ipaserver/plugins/trust.py +++ b/ipaserver/plugins/trust.py @@ -657,48 +657,52 @@ class trust_add(LDAPCreate): Str('realm_admin?', cli_name='admin', label=_("Active Directory domain administrator"), - ), + ), Password('realm_passwd?', - cli_name='password', - label=_("Active Directory domain administrator's password"), - confirm=False, - ), + cli_name='password', + label=_("Active Directory domain administrator's password"), + confirm=False, + ), Str('realm_server?', cli_name='server', - label=_('Domain controller for the Active Directory domain (optional)'), - ), + label=_('Domain controller for the Active Directory domain ' + '(optional)'), + ), Password('trust_secret?', - cli_name='trust_secret', - label=_('Shared secret for the trust'), - confirm=False, - ), + cli_name='trust_secret', + label=_('Shared secret for the trust'), + confirm=False, + ), Int('base_id?', cli_name='base_id', - label=_('First Posix ID of the range reserved for the trusted domain'), - ), + label=_('First Posix ID of the range reserved for the ' + 'trusted domain'), + ), Int('range_size?', cli_name='range_size', - label=_('Size of the ID range reserved for the trusted domain'), - ), + label=_('Size of the ID range reserved for the trusted domain') + ), StrEnum('range_type?', - label=_('Range type'), - cli_name='range_type', - doc=(_('Type of trusted domain ID range, one of {vals}' - .format(vals=', '.join(range_types.keys())))), - values=tuple(range_types.keys()), - ), + label=_('Range type'), + cli_name='range_type', + doc=(_('Type of trusted domain ID range, one of {vals}' + .format(vals=', '.join(sorted(range_types))))), + values=sorted(range_types), + ), Bool('bidirectional?', label=_('Two-way trust'), cli_name='two_way', - doc=(_('Establish bi-directional trust. By default trust is inbound one-way only.')), + doc=(_('Establish bi-directional trust. By default trust is ' + 'inbound one-way only.')), default=False, - ), + ), Bool('external?', label=_('External trust'), cli_name='external', - doc=(_('Establish external trust to a domain in another forest. The trust is not transitive beyond the domain.')), + doc=_('Establish external trust to a domain in another forest. ' + 'The trust is not transitive beyond the domain.'), default=False, - ), + ), ) msg_summary = _('Added Active Directory trust for realm "%(value)s"') diff --git a/ipatests/test_ipalib/test_output.py b/ipatests/test_ipalib/test_output.py index ed734ffd4b..954b2a34f5 100644 --- a/ipatests/test_ipalib/test_output.py +++ b/ipatests/test_ipalib/test_output.py @@ -53,14 +53,18 @@ def test_repr(self): o = self.cls('aye') assert repr(o) == "Output('aye')" o = self.cls('aye', type=int, doc='An A, aye?') - assert repr(o) == "Output('aye', type=[%r], doc='An A, aye?')" % int + assert repr(o) == ( + "Output('aye', type=[<type 'int'>], doc='An A, aye?')" + ) class Entry(self.cls): pass o = Entry('aye') assert repr(o) == "Entry('aye')" o = Entry('aye', type=int, doc='An A, aye?') - assert repr(o) == "Entry('aye', type=[%r], doc='An A, aye?')" % int + assert repr(o) == ( + "Entry('aye', type=[<type 'int'>], doc='An A, aye?')" + ) class test_ListOfEntries(ClassChecker): From e318101893ff45d776e8eee5a2d544c37d930006 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Wed, 14 Feb 2018 17:00:44 +0100 Subject: [PATCH 2/2] Run API and ACI under Python 2 and 3 Make it possible to run API, ACI, and potests under Python 3. Signed-off-by: Christian Heimes <chei...@redhat.com> --- Makefile.am | 17 ++++++++++------- po/Makefile.hack.in | 7 ++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1e200f117d..9bb1a94e9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -174,10 +174,10 @@ endif $(MAKE) $(AM_MAKEFLAGS) acilint apilint polint jslint check $(MAKE) $(AM_MAKEFLAGS) PYTHON=$(PYTHON2) pylint if WITH_PYTHON3 - @ # just tests and pylint on Python 3 + @ # just tests, aci, api and pylint on Python 3 PYTHONPATH=$(abspath $(top_srcdir)) $(PYTHON3) ipatests/ipa-run-tests \ --ipaclient-unittests - $(MAKE) $(AM_MAKEFLAGS) PYTHON=$(PYTHON3) pylint + $(MAKE) $(AM_MAKEFLAGS) PYTHON=$(PYTHON3) acilint apilint pylint else @echo "WARNING: python3 not available" endif @@ -186,10 +186,12 @@ endif .PHONY: fastcheck fasttest fastlint fastcheck: if WITH_PYTHON2 - @$(MAKE) -j1 $(AM_MAKEFLAGS) PYTHON=$(PYTHON2) fastlint fasttest + @$(MAKE) -j1 $(AM_MAKEFLAGS) PYTHON=$(PYTHON2) \ + fastlint fasttest apilint acilint endif if WITH_PYTHON3 - @$(MAKE) -j1 $(AM_MAKEFLAGS) PYTHON=$(PYTHON3) fastlint fasttest + @$(MAKE) -j1 $(AM_MAKEFLAGS) PYTHON=$(PYTHON3) \ + fastlint fasttest apilint acilint endif fasttest: $(GENERATED_PYTHON_FILES) ipasetup.py @@ -236,15 +238,16 @@ $(top_builddir)/ipapython/version.py: .PHONY: acilint acilint: $(GENERATED_PYTHON_FILES) - cd $(srcdir); ./makeaci --validate + cd $(srcdir); $(PYTHON) ./makeaci --validate .PHONY: apilint apilint: $(GENERATED_PYTHON_FILES) - cd $(srcdir); ./makeapi --validate + cd $(srcdir); $(PYTHON) ./makeapi --validate .PHONY: polint polint: - $(MAKE) -C $(srcdir)/po validate-src-strings validate-po test-gettext + $(MAKE) -C $(srcdir)/po PYTHON=$(PYTHON) \ + validate-src-strings validate-po test-gettext # Run pylint for all python files. Finds all python files/packages, skips # folders rpmbuild, freeipa-* and dist. Skip (match, but don't print) .*, diff --git a/po/Makefile.hack.in b/po/Makefile.hack.in index 90727c460c..c57f1e1506 100644 --- a/po/Makefile.hack.in +++ b/po/Makefile.hack.in @@ -6,6 +6,7 @@ DISTFILES.common.extra3 = Makefile.hack.in IPA_TEST_I18N = @top_srcdir@/ipatests/i18n.py MSGATTRIB = @MSGATTRIB@ +PYTHON = @PYTHON@ .PHONY: strip-po strip-po: @@ -24,13 +25,13 @@ clean: mostlyclean # linters test-gettext: $(DOMAIN).pot - $(IPA_TEST_I18N) --test-gettext + $(PYTHON) $(IPA_TEST_I18N) --test-gettext validate-pot: $(DOMAIN).pot - $(IPA_TEST_I18N) --show-strings --validate-pot $(DOMAIN).pot + $(PYTHON) $(IPA_TEST_I18N) --show-strings --validate-pot $(DOMAIN).pot validate-po: $(DOMAIN).pot - $(IPA_TEST_I18N) --show-strings --validate-po $(POFILES) + $(PYTHON) $(IPA_TEST_I18N) --show-strings --validate-po $(POFILES) # forcefully re-generate .pot file and test it validate-src-strings: $(DOMAIN).pot-update
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org