ucsschool.importer.utils package

Submodules

ucsschool.importer.utils.config_pyhook module

Base class for configuration hooks.

class ucsschool.importer.utils.config_pyhook.ConfigPyHook(lo=None, dry_run=None, *args, **kwargs)[source]

Bases: ucsschool.importer.utils.import_pyhook.ImportPyHook

Hook to manipulate the configuration after reading the configuration files and applying the command line arguments.

The base class’ __init__() provides the following attributes:

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

Parameters:
priority = {'post_config_files_read': None}
post_config_files_read(config, used_conffiles, used_kwargs)[source]

Hook that runs after reading the configuration files used_conffiles and applying the command line arguments used_kwargs. Resulting configuration is config, which can be manipulated and must be returned.

Parameters:
  • config (ReadOnlyDict) – configuration that will be used by the import if not modified here, not yet read-only.
  • used_conffiles (list) – configuration files read and applied
  • used_kwargs (dict) – command line options read and applied
Returns:

config dict

Return type:

ReadOnlyDict

ucsschool.importer.utils.configuration_checks module

Configuration checks.

After the configuration has been read, checks run.

To add your own checks, subclass ConfigurationChecks, save the module in /usr/share/ucs-school-import/checks and add its module name (without .py) to the list in the configuration key configuration_checks.

Remove defaults from your configuration_checks only if you know what you are doing.


Example: Save the following to /usr/share/ucs-school-import/checks/mychecks.py:

>>> from ucsschool.importer.exceptions import InitialisationError
>>> from ucsschool.importer.utils.configuration_checks import ConfigurationChecks
>>>
>>> class MyConfigurationChecks(ConfigurationChecks):
>>>     def test_nonzero_deactivation_grace(self):
>>>             if self.config.get('deletion_grace_period', {}).get('deactivation', 0) == 0:
>>>                     raise InitialisationError('deletion_grace_period:deactivation must not be zero.')

Then add a configuration entry to /var/lib/ucs-school-import/configs/user_import.json:

{
[..]
    "configuration_checks": ["defaults", "mychecks"]
}
class ucsschool.importer.utils.configuration_checks.ConfigurationChecks(config)[source]

Bases: object

Base class for configuration checks.

Provides the configuration singleton in self.config, a read-only LDAP connection object in self.lo and a logging instance in self.logger.

All methods with names starting with test_ will be executed in alphanumerical order. Failing tests should raise a py:exception:ucsschool.importer.exceptions.InitialisationError exception.

ucsschool.importer.utils.format_pyhook module

Base class for all Python based format hooks.

class ucsschool.importer.utils.format_pyhook.FormatPyHook(*args, **kwargs)[source]

Bases: ucsschool.lib.pyhooks.pyhook.PyHook

Format hook base class

The base class’ __init__() provides a logger instance:

self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function.

priority = {'patch_fields_teacher_and_staff': None, 'patch_fields_staff': None, 'patch_fields_teacher': None, 'patch_fields_student': None}
properties = ()
logger = None

Python logging instance

patch_fields_staff(property_name, fields)[source]

Run code before formatting an property using a schema in format_from_scheme().

Parameters:
  • property_name (str) – Name of property_name that will be formatted
  • fields (dict) – dictionary with the users attributes and udm_properties
Returns:

fields dictionary that be used by format_from_scheme()

Return type:

dict

patch_fields_student(property_name, fields)[source]

Run code before formatting an property using a schema in format_from_scheme().

Parameters:
  • property_name (str) – Name of property_name that will be formatted
  • fields (dict) – dictionary with the users attributes and udm_properties
Returns:

fields dictionary that be used by format_from_scheme()

Return type:

dict

patch_fields_teacher(property_name, fields)[source]

Run code before formatting an property using a schema in format_from_scheme().

Parameters:
  • property_name (str) – Name of property_name that will be formatted
  • fields (dict) – dictionary with the users attributes and udm_properties
Returns:

fields dictionary that be used by format_from_scheme()

Return type:

dict

patch_fields_teacher_and_staff(property_name, fields)[source]

Run code before formatting a property using a schema in format_from_scheme().

Parameters:
  • property_name (str) – Name of property_name that will be formatted
  • fields (dict) – dictionary with the users attributes and udm_properties
Returns:

fields dictionary that be used by format_from_scheme()

Return type:

dict

ucsschool.importer.utils.import_pyhook module

Base class for all Python based import hooks.

class ucsschool.importer.utils.import_pyhook.ImportPyHook(lo=None, dry_run=None, *args, **kwargs)[source]

Bases: ucsschool.lib.pyhooks.pyhook.PyHook

Base class for Python based import hooks.

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

Parameters:
supports_dry_run = False
dry_run = None

Whether this is a dry-run

lo = None

LDAP connection object

logger = None

Python logging instance

class ucsschool.importer.utils.import_pyhook.ImportPyHookLoader(pyhooks_base_path)[source]

Bases: object

Load and initialize hooks.

If hooks should be instantiated with arguments, use init_hook() before call_hook().

_pyhook_obj_cache = {}
init_hook(hook_cls, filter_func=None, *args, **kwargs)[source]

Load and initialize hook class hook_cls.

Parameters:
  • args (tuple) – arguments to pass to __init__ of hooks
  • kwargs (dict) – arguments to pass to __init__ of hooks
Returns:

mapping from method names to list of methods of initialized hook objects, sorted by method priority

Return type:

dict[str, list[callable]]

call_hooks(hook_cls, func_name, *args, **kwargs)[source]

Run hooks with name func_name from class hook_cls.

Parameters:
  • hook_cls – class object - load and run hooks that are a subclass of this
  • func_name (str) – name of method to run in each hook
  • args – arguments to pass to hook function
  • kwargs – arguments to pass to hook function
Returns:

list of when all executed hooks returned

Return type:

list

ucsschool.importer.utils.import_pyhook.get_import_pyhooks(hook_cls, filter_func=None, *args, **kwargs)[source]

Retrieve (and initialize subclasses of hook_cls, if not yet done) pyhooks of type hook_cls. Results are cached.

If no argument must be passed to the hook_cls __init__() or PyHooksLoader, then it is not necessary to call this function, just use run_import_pyhooks() directly.

Convenience function for easy usage of PyHooksLoader.

Parameters:
  • hook_cls (ucsschool.importer.utils.import_pyhook.ImportPyHook) – class object - load and run hooks that are a subclass of this
  • filter_func (callable or None) – function to filter out undesired hook classes (takes a class and returns a bool), passed to PyHooksLoader
  • args – arguments to pass to __init__ of hooks
  • kwargs – arguments to pass to __init__ of hooks
Returns:

mapping from method names to list of methods of initialized hook objects, sorted by method priority

Return type:

dict[str, list[callable]]

ucsschool.importer.utils.import_pyhook.run_import_pyhooks(hook_cls, func_name, *args, **kwargs)[source]

Execute method func_name of subclasses of hook_cls, load and initialize if required.

Convenience function for easy usage of PyHooksLoader.

Parameters:
  • hook_cls (ucsschool.importer.utils.import_pyhook.ImportPyHook) – class object - load and run hooks that are a subclass of this
  • func_name (str) – name of method to run in each hook
  • args – arguments to pass to hook function func_name
  • kwargs – arguments to pass to hook function func_name
Returns:

list of when all executed hooks returned

Return type:

list

ucsschool.importer.utils.ldap_connection module

Create LDAP connections for import.

ucsschool.importer.utils.ldap_connection.get_admin_connection()[source]

Read-write cn=admin connection.

Return type:tuple(univention.admin.uldap.access, univention.admin.uldap.position)
ucsschool.importer.utils.ldap_connection.get_machine_connection()[source]

Read-write machine connection.

Return type:tuple(univention.admin.uldap.access, univention.admin.uldap.position)
ucsschool.importer.utils.ldap_connection.get_unprivileged_connection()[source]

Unprivileged read-write connection.

Return type:tuple(univention.admin.uldap.access, univention.admin.uldap.position)
class ucsschool.importer.utils.ldap_connection.ReadOnlyAccess(*args, **kwargs)[source]

Bases: univention.admin.uldap.access

LDAP access class that prevents LDAP write access.

Must be a descendant of univention.admin.uldap.access, or UDM will raise a TypeError.

add(*args, **kwargs)[source]
modify(*args, **kwargs)[source]
rename(*args, **kwargs)[source]
delete(*args, **kwargs)[source]
ucsschool.importer.utils.ldap_connection.get_readonly_connection()[source]

Read-only cn=admin connection.

Return type:tuple(univention.admin.uldap.access, univention.admin.uldap.position)

ucsschool.importer.utils.logging module

Central place to get logger for import.

ucsschool.importer.utils.logging.get_logger()[source]

Get a logging instance with name ucsschool.

Deprecated since version 4.4: v2 Use logging.getLogger(__name__) and get_stream_handler(), get_file_handler().

Returns:Logger
Return type:logging.Logger
ucsschool.importer.utils.logging.make_stdout_verbose()[source]
ucsschool.importer.utils.logging.add_file_handler(filename, uid=None, gid=None, mode=None)[source]
ucsschool.importer.utils.logging.move_our_handlers_to_lib_logger()[source]

Move logging handlers from ucsschool.import to ucsschool logger.

Deprecated since version 4.4: v2 Use logging.getLogger(__name__) and get_stream_handler(), get_file_handler() for the logger hierarchie required.

ucsschool.importer.utils.post_read_pyhook module

Base class for all Python based Post-Read-Pyhooks.

class ucsschool.importer.utils.post_read_pyhook.PostReadPyHook(lo=None, dry_run=None, *args, **kwargs)[source]

Bases: ucsschool.importer.utils.import_pyhook.ImportPyHook

Hook that is called directly after data has been read from CSV/...

The base class’ __init__() provides the following attributes:

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

Parameters:
priority = {'entry_read': None, 'all_entries_read': None}
entry_read(entry_count, input_data, input_dict)[source]

Run code after an entry has been read and saved in input_data and input_dict. This hook may alter input_data and input_dict to modify the input data. This function may raise the exception UcsSchoolImportSkipImportRecord to ignore the read import data.

Parameters:
  • entry_count (int) – index of the data entry (e.g. line of the CSV file)
  • input_data (list[str]) – input data as raw as possible (e.g. raw CSV columns). The input_data may be changed.
  • input_dict (dict[str, str]) – input data mapped to column names. The input_dict may be changed.
Returns:

None

Raises:

UcsSchoolImportSkipImportRecord – if an entry (e.g. a CSV line) should be skipped

all_entries_read(imported_users, errors)[source]

Run code after all entries have been read. ImportUser objects for all lines are passed to the hook. Also errors are passed. Please note that the “entry_read” hook method may skip one or several input records, so they may be missing in imported_users. errors contains a list of catched errors/exceptions.

Parameters:
  • imported_users (list[ImportUser]) – list of ImportUser objects created from the input records
  • errors (list[Exception]) – list of exceptions that are caught during processing the input records
Returns:

None

ucsschool.importer.utils.pre_read_pyhook module

Base class for all Python based pre-read hooks.

class ucsschool.importer.utils.pre_read_pyhook.PreReadPyHook(lo=None, dry_run=False, *args, **kwargs)[source]

Bases: ucsschool.importer.utils.import_pyhook.ImportPyHook

Hook that is called before starting to read the input file.

The base class’ __init__() provides the following attributes:

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance
  • self.config # read-only import configuration

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

priority = {'pre_read': None}
pre_read()[source]

Run code before starting to read the input file.

Returns:None

ucsschool.importer.utils.result_pyhook module

Base class for all Python based Result-Pyhooks.

class ucsschool.importer.utils.result_pyhook.ResultPyHook(lo=None, dry_run=None, *args, **kwargs)[source]

Bases: ucsschool.importer.utils.import_pyhook.ImportPyHook

Hook that is called after import has finished.

The base class’ __init__() provides the following attributes:

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

Parameters:
priority = {'user_result': None}
user_result(user_import_data)[source]

Run code after user import has finished. Relevant data from the UserImport class is passed to this hook, so result summaries etc are possible.

Parameters:user_import_data (UserImportData) – relevant data from the UserImport class
Returns:None

ucsschool.importer.utils.shell module

ucsschool.importer.utils.test_user_creator module

Class to create lots of test users.

class ucsschool.importer.utils.test_user_creator.TestUserCreator(ous, staff=0, students=0, teachers=0, staffteachers=0, classes=0, inclasses=2, schools=2, email=False)[source]

Bases: object

static get_test_data(filename)[source]
make_classes()[source]
_get_new_given_name()[source]
_get_new_family_name()[source]
_class_name_gen(school)[source]
_get_class_name(school)[source]
static _get_maildomain()[source]
make_users()[source]

ucsschool.importer.utils.user_pyhook module

Base class for all Python based User hooks.

class ucsschool.importer.utils.user_pyhook.UserPyHook(lo=None, dry_run=None, *args, **kwargs)[source]

Bases: ucsschool.importer.utils.import_pyhook.ImportPyHook

Base class for Python based user import hooks.

An example is provided in /usr/share/doc/ucs-school-import/hook_example.py

The base class’ __init__() provides the following attributes:

  • self.dry_run # whether hook is executed during a dry-run (1)
  • self.lo # LDAP connection object (2)
  • self.logger # Python logging instance

If multiple hook classes are found, hook functions with higher priority numbers run before those with lower priorities. None disables a function (no need to remove it / comment it out).

(1) Hooks are only executed during dry-runs, if the class attribute supports_dry_run is set to True (default is False). Hooks with supports_dry_run == True must not modify LDAP objects. Therefore the LDAP connection object self.lo will be a read-only connection during a dry-run. (2) Read-write cn=admin connection in a real run, read-only cn=admin connection during a dry-run.

Parameters:
priority = {'pre_remove': None, 'pre_modify': None, 'post_create': None, 'pre_create': None, 'post_remove': None, 'post_move': None, 'post_modify': None, 'pre_move': None}
pre_create(user)[source]

Run code before creating a user.

  • The user does not exist in LDAP, yet.
  • user.dn is the future DN of the user, if username and school does not change.
  • user.input_data contains the (csv) input data, if the user was create during an import job
  • set priority[“pre_create”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
post_create(user)[source]

Run code after creating a user.

  • The hook is only executed if adding the user succeeded.
  • user will be an ImportUser, loaded from LDAP.
  • Do not run user.modify(), it will create a recursion. Please use user.modify_without_hooks().
  • set priority[“post_create”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
pre_modify(user)[source]

Run code before modifying a user.

  • user will be a ImportUser, loaded from LDAP.
  • set priority[“pre_modify”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
post_modify(user)[source]

Run code after modifying a user.

  • The hook is only executed if modifying the user succeeded.
  • user will be an ImportUser, loaded from LDAP.
  • Do not run user.modify(), it will create a recursion. Please use user.modify_without_hooks().
  • If running in an import job, the user may not have been removed, but merely deactivated. If user.udm_properties[“ucsschoolPurgeTimestamp”] is set, the user is marked for removal.
  • set priority[“post_modify”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
pre_move(user)[source]

Run code before changing a users primary school (position).

  • user will be an ImportUser, loaded from LDAP.
  • set priority[“pre_move”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
post_move(user)[source]

Run code after changing a users primary school (position).

  • The hook is only executed if moving the user succeeded.
  • user will be an ImportUser, loaded from LDAP.
  • Do not run user.modify(), it will create a recursion. Please use user.modify_without_hooks().
  • set priority[“post_move”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
pre_remove(user)[source]

Run code before deleting a user.

  • user will be an ImportUser, loaded from LDAP.
  • set priority[“pre_remove”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None
post_remove(user)[source]

Run code after deleting a user.

  • The hook is only executed if the deleting the user succeeded.
  • user will be an ImportUser, loaded from LDAP.
  • The user was removed, do not try to modify() it.
  • set priority[“post_remove”] to an int, to enable this method
Parameters:user (ImportUser) – User (or a subclass of it, eg. ImportUser)
Returns:None

ucsschool.importer.utils.username_handler module

Create historically unique usernames/email addresses.

class ucsschool.importer.utils.username_handler.NameCounterStorageBackend[source]

Bases: object

create(name, value)[source]

Store a value for a new name.

Parameters:
  • name (str) – name
  • value (int) – value to store
Returns:

None

Raises:

NameKeyExists – if a value is already stored to such a name

modify(name, old_value, new_value)[source]

Store a value for an existing name.

Parameters:
  • name (str) – name
  • old_value (int) – old value
  • new_value (int) – new value
Returns:

None

Raises:

NameKeyExists – if no value is stored by that name

retrieve(name)[source]

Retrieve a value for a name.

Parameters:

name (str) – name to retrieve

Returns:

int

Raises:
  • NoValueStored – if no value is stored by that name
  • BadValueStored – if the value has a bad format
remove(name)[source]

Remove a name from storage.

Parameters:name (str) – name
Returns:None
purge()[source]

Remove all names from storage. NEVER do this in a production environment!

Returns:None
class ucsschool.importer.utils.username_handler.LdapStorageBackend(attribute_storage_name, lo=None, pos=None)[source]

Bases: ucsschool.importer.utils.username_handler.NameCounterStorageBackend

Prior to using this class, a node must exist in LDAP: ‘cn=unique-<attribute_name>,cn=ucsschool,cn=univention,<base>’.

create(name, value)[source]
modify(name, old_value, new_value)[source]
retrieve(name)[source]
remove(name)[source]
purge()[source]

Remove all names from storage. NEVER do this in a production environment!

Returns:None
class ucsschool.importer.utils.username_handler.MemoryStorageBackend(attribute_storage_name)[source]

Bases: ucsschool.importer.utils.username_handler.NameCounterStorageBackend

create(name, value)[source]
modify(name, old_value, new_value)[source]
retrieve(name)[source]
remove(name)[source]

This will remove the key only from memory. It may still be stored in the LDAP backend.

Parameters:name (str) – name
Returns:None
purge()[source]

This will remove keys only from memory. They may still be stored in the LDAP backend.

Returns:None
class ucsschool.importer.utils.username_handler.UsernameHandler(max_length, dry_run=True)[source]

Bases: object

>>> BAD_CHARS = ''.join(sorted(set(map(chr, range(128))) - set(UsernameHandler(20).allowed_chars)))
>>> UsernameHandler(20).format_username('Max.Mustermann')
'Max.Mustermann'
>>> UsernameHandler(20).format_username('Foo[COUNTER2][COUNTER2]')   
Traceback (most recent call last):
...
FormatError:
>>> UsernameHandler(20).format_username('.')
''
>>> UsernameHandler(20).format_username('.Max.Mustermann.')
'Max.Mustermann'
>>> UsernameHandler(4).format_username('Max.Mustermann')
'Max'
>>> for c in BAD_CHARS:
...  assert 'Max' == UsernameHandler(20).format_username('Ma%sx' % (c,))
...
>>> UsernameHandler(20).format_username('Max.Mustermann12.4567890')
'Max.Mustermann12.456'
>>> for c in '.1032547698ACBEDGFIHKJMLONQPSRUTWVYXZacbedgfihkjmlonqpsrutwvyxz':
...  assert 'Ma%sx' % (c,) == UsernameHandler(20).format_username('Ma%sx' % (c,))
...
>>> UsernameHandler(20).format_username('Max[Muster]Mann')
'MaxMusterMann'
>>> UsernameHandler(20).format_username('Max[ALWAYSCOUNTER].Mustermann')
'Max1.Mustermann'
>>> UsernameHandler(20).format_username('Max[ALWAYSCOUNTER].Mustermann')
'Max2.Mustermann'
>>> UsernameHandler(20).format_username('Max[ALWAYSCOUNTER].Mustermann')
'Max3.Mustermann'
>>> UsernameHandler(20).format_username('Max[COUNTER2].Mustermann')
'Max4.Mustermann'
>>> UsernameHandler(20).format_username('Maria[ALWAYSCOUNTER].Musterfrau')
'Maria1.Musterfrau'
>>> UsernameHandler(20).format_username('Moritz[COUNTER2]')
'Moritz'
>>> UsernameHandler(20).format_username('Moritz[COUNTER2]')
'Moritz2'
>>> UsernameHandler(20).format_username('Foo[ALWAYSCOUNTER]')
'Foo1'
>>> for i, c in enumerate(BAD_CHARS + BAD_CHARS, 2):
...  username = UsernameHandler(20).format_username('Fo%so[ALWAYSCOUNTER]' % (c,))
...  assert 'Foo%d' % (i,) == username, (username, i, c)
>>> UsernameHandler(8).format_username('aaaa[COUNTER2]bbbbcccc')
'aaaab'
>>> UsernameHandler(8).format_username('aaaa[COUNTER2]bbbbcccc')
'aaaa2b'
>>> UsernameHandler(8).format_username('bbbb[ALWAYSCOUNTER]ccccdddd')
'bbbb1c'
>>> UsernameHandler(8).format_username('bbbb[ALWAYSCOUNTER]ccccdddd')
'bbbb2c'
>>> UsernameHandler(20).format_username('..[ALWAYSCOUNTER]..')
''
>>> UsernameHandler(20).format_username('[ALWAYSCOUNTER]')
''
>>> UsernameHandler(20).format_username('[FOObar]')
'FOObar'
Parameters:max_length (int) – created usernames will be no longer

than this :param bool dry_run: if False use LDAP to store already-used usernames if True store for one run only in memory

attribute_name = 'username'
attribute_storage_name = 'usernames'
allowed_chars
get_storage_backend()[source]
Returns:NameCounterStorageBackend instance
Return type:NameCounterStorageBackend
remove_bad_chars(name)[source]

Remove characters disallowed for names. * Name must only contain numbers, letters and dots, and may not be ‘admin’! * Name must not start or end in a dot.

Parameters:name (str) – name to check
Returns:copy of input, possibly modified
Return type:str
format_name(name, max_length=None)[source]

Create a username/email from <name>, possibly replacing a counter variable. * This is intended to be called before/by/after ImportUser.format_from_scheme(). * Supports inserting the counter anywhere in the name, as long as its length does not overflow max_length. * Only one counter variable is allowed. * Counters should run only to 999. The algorithm will not honor max_length for higher numbers! * Subclass->override counter_variable_to_function() and the called methods to support other schemes than [ALWAYSCOUNTER] and [COUNTER2] or change their meaning.

Parameters:
  • name (str) – username/email, possibly a template
  • max_length (int) – overwrite max length specified at object instanciation time
Returns:

unique name

Return type:

str

Raises:

FormatError – if more than one counter variable was found in the scheme

format_username(name)[source]

Deprecated method. Please use format_name() instead.

counter_variable_to_function

Subclass->override this to support other variables than [ALWAYSCOUNTER] and [COUNTER2] or change their meaning. Add/Modify corresponding methods in your subclass. Variables have to start with ‘[‘, end with ‘]’ and must be all upper case.

Returns:mapping: variable name -> function
Return type:dict
always_counter(name_base)[source]

[ALWAYSCOUNTER]

Parameters:name_base (str) – the name without [ALWAYSCOUNTER]
Returns:number to append to name
Return type:str
counter2(name_base)[source]

[COUNTER2]

Parameters:name_base (str) – the name without [COUNTER2]
Returns:number to append to name
Return type:str
get_and_raise(name_base, initial_value)[source]

Returns the current counter value or initial_value if unset and stores it raised by 1.

Parameters:
  • name_base (str) – name without []
  • initial_value (str) – lowest value
Returns:

current counter value

Return type:

str

class ucsschool.importer.utils.username_handler.EmailHandler(max_length=254, dry_run=True)[source]

Bases: ucsschool.importer.utils.username_handler.UsernameHandler

Create unique email addresses. * Maximum length of an email address is 254 characters. * Applies counters [ALWAYSCOUNTER/COUNTER2] to local part (left of @) only.

:param int max_length maximum length of email address :param bool dry_run: if False use LDAP to store already-used email addresses if True store for one run only in memory

attribute_name = 'email'
attribute_storage_name = 'email'
allowed_chars
remove_bad_chars(name)[source]

Space is actually allowed (inside a quoted string), but we’ll remove it anyway. (Although technically allowed, not all mail servers support it.)

format_name(name, max_length=None)[source]

ucsschool.importer.utils.utils module

Diverse helper functions.

ucsschool.importer.utils.utils.mkdir_p(dir_name, user, group, mode)[source]

Recursively create directories (like “mkdir -p”).

Parameters:
  • dir_name (str) – path to create
  • user (str) – username of owner of new directories
  • group (str) – group name for ownership of new directories
  • mode (octal) – permission bits to set for new directories
Returns:

None

Return type:

None

ucsschool.importer.utils.utils.get_ldap_mapping_for_udm_property(udm_prop, udm_type)[source]

Get the name of the LDAP attribute, a UDM property is mapped to.

Parameters:
  • udm_prop (str) – name of UDM property
  • udm_type (str) – name of UDM module (e.g. ‘users/user’)
Returns:

name of LDAP attribute or empty str if no mapping was found

Return type:

str

ucsschool.importer.utils.utils.nullcontext(*args, **kwds)[source]

Context manager that does nothing.