ucsschool.importer.utils package#
Submodules#
ucsschool.importer.utils.computer_import module#
- ucsschool.importer.utils.computer_import.call_hook(lo: access, meth_name: str, obj: SchoolComputer, line: List[str]) None[source]#
- ucsschool.importer.utils.computer_import.get_ip_iface(ip_address: str) IPv4Interface[source]#
ucsschool.importer.utils.computer_pyhook module#
Base class for all Python based Computer hooks.
- class ucsschool.importer.utils.computer_pyhook.ComputerPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookBase class for Python based computer import hooks.
The base class’
__init__()provides the following attributes: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).
- Parameters:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- pre_create(computer: SchoolComputer, row: List[str]) None[source]#
Run code before creating a computer.
The computer does not exist in LDAP, yet.
computer.dn is the future DN of the computer,
set priority[“pre_create”] to an int, to enable this method
- Parameters:
computer (SchoolComputer) – Computer (subclass of SchoolComputer)
- Returns:
None
- post_create(computer: SchoolComputer, row: List[str]) None[source]#
Run code after creating a computer.
The hook is only executed if adding the computer succeeded.
computer will be an
SchoolComputer, loaded from LDAP.set priority[“post_create”] to an int, to enable this method
- Parameters:
computer (SchoolComputer) – Computer (subclass of SchoolComputer)
- Returns:
None
ucsschool.importer.utils.config_pyhook module#
Base class for configuration hooks.
- class ucsschool.importer.utils.config_pyhook.ConfigPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookHook 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority = {'post_config_files_read': None}#
- post_config_files_read(config: ReadOnlyDict, used_conffiles: List[str], used_kwargs: Dict[str, Any]) ReadOnlyDict[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:
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: ReadOnlyDict)[source]#
Bases:
objectBase class for configuration checks.
Provides the configuration singleton in
self.config, a read-only LDAP connection object inself.loand a logging instance inself.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.constants module#
ucsschool.importer.utils.format_pyhook module#
Base class for all Python based format hooks.
- class ucsschool.importer.utils.format_pyhook.FormatPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookFormat hook base class
See ImportPyHook base class for documentation regarding the class’ attributes.
- Parameters:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority = {'patch_fields_staff': None, 'patch_fields_student': None, 'patch_fields_teacher': None, 'patch_fields_teacher_and_staff': None}#
- properties = ()#
- patch_fields_staff(property_name, fields)[source]#
Run code before formatting an property using a schema in format_from_scheme().
- patch_fields_student(property_name, fields)[source]#
Run code before formatting an property using a schema in format_from_scheme().
- patch_fields_teacher(property_name, fields)[source]#
Run code before formatting an property using a schema in format_from_scheme().
ucsschool.importer.utils.import_pyhook module#
Base class for all Python based import hooks.
- class ucsschool.importer.utils.import_pyhook.ImportPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
PyHookBase 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- supports_dry_run = False#
- dry_run#
Whether this is a dry-run
- lo: univention.admin.uldap.access#
LDAP connection object
- logger: logging.Logger#
Python logging instance
- class ucsschool.importer.utils.import_pyhook.ImportPyHookLoader(pyhooks_base_path: str)[source]#
Bases:
objectLoad and initialize hooks.
If hooks should be instantiated with arguments, use
init_hook()beforecall_hook().- init_hook(hook_cls: Type[ImportPyHookTV] | str, filter_func: Callable[[Type[ImportPyHookTV]], bool] | None = None, *args: Any, **kwargs: Any) Dict[str, List[Callable[[...], Any]]][source]#
Load and initialize hook class hook_cls.
- Parameters:
hook_cls (ucsschool.importer.utils.import_pyhook.ImportPyHook or str) – 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 (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:
- ucsschool.importer.utils.import_pyhook.get_import_pyhooks(hook_cls: Type[ImportPyHookTV] | str, filter_func: Callable[[Type[ImportPyHookTV]], bool] | None = None, *args: Any, **kwargs: Any) Dict[str, List[Callable[[...], Any]]][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__()orPyHooksLoader, then it is not necessary to call this function, just userun_import_pyhooks()directly.Convenience function for easy usage of PyHooksLoader.
- Parameters:
hook_cls (ucsschool.importer.utils.import_pyhook.ImportPyHook or str) – class object or fully dotted Python path to a class definition - 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:
- ucsschool.importer.utils.import_pyhook.run_import_pyhooks(hook_cls: Type[ImportPyHookTV] | str, func_name: str, *args: Any, **kwargs: Any) List[Any][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 or str) – class object or fully dotted Python path to a class definition - 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:
ucsschool.importer.utils.ldap_connection module#
Create LDAP connections for import.
- ucsschool.importer.utils.ldap_connection.get_admin_connection() Tuple[LoType, PoType][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() Tuple[LoType, PoType][source]#
Read-write machine connection.
- Return type:
tuple(univention.admin.uldap.access, univention.admin.uldap.position)
- ucsschool.importer.utils.ldap_connection.get_unprivileged_connection() Tuple[LoType, PoType][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:
accessLDAP access class that prevents LDAP write access.
Must be a descendant of
univention.admin.uldap.access, or UDM will raise aTypeError.- Parameters:
host – The hostname of the LDAP server.
port – The TCP port number of the LDAP server.
base – The base distinguished name.
binddn – The distinguished name of the account.
bindpw – The user password for simple authentication.
start_tls – Negotiate TLS with server. If 2 is given, the command will require the operation to be successful.
lo – LDAP connection.
follow_referral – Follow LDAP referrals.
uri – LDAP connection string.
- add(*args, **kwargs)[source]#
Add LDAP entry at distinguished name and attributes in add_list=(attribute-name, old-values. new-values) or (attribute-name, new-values).
- Parameters:
dn (str) – The distinguished name of the object to add.
al – The add-list of 2-tuples (attribute-name, new-values).
exceptions (bool) – Raise the low level exception instead of the wrapping UDM exceptions.
serverctrls – a list of ldap.controls.LDAPControl instances sent to the server along with the LDAP request
ignore_license (bool) – Ignore license check if True.
response (dict) – An optional dictionary to receive the server controls of the result.
- Raises:
univention.admin.uexceptions.licenseDisableModify – if the UCS licence prohibits any modificcation
univention.admin.uexceptions.objectExists – if the LDAP object already exists.
univention.admin.uexceptions.permissionDenied – if the user does not have the required permissions.
univention.admin.uexceptions.ldapError – if the syntax of the DN is invalid.
univention.admin.uexceptions.ldapError – on any other LDAP error.
- modify(*args, **kwargs)[source]#
Modify LDAP entry DN with attributes in changes=(attribute-name, old-values, new-values).
- Parameters:
dn (str) – The distinguished name of the object to modify.
changes – The modify-list of 3-tuples (attribute-name, old-values, new-values).
exceptions (bool) – Raise the low level exception instead of the wrapping UDM exceptions.
ignore_license (bool) – Ignore license check if True.
serverctrls – a list of ldap.controls.LDAPControl instances sent to the server along with the LDAP request
response (dict) – An optional dictionary to receive the server controls of the result.
- Returns:
The distinguished name.
- rename(*args, **kwargs)[source]#
Rename a LDAP object.
- Parameters:
dn – The old distinguished name of the object to rename.
newdn – The new distinguished name of the object to rename.
move_childs – Also rename the sub children. Must be 0 always as 1 is not implemented.
ignore_license – Ignore license check if True.
serverctrls – a list of ldap.controls.LDAPControl instances sent to the server along with the LDAP request
response – An optional dictionary to receive the server controls of the result.
- delete(*args, **kwargs)[source]#
Delete a LDAP object.
- Parameters:
- Raises:
univention.admin.uexceptions.noObject – if the object does not exist.
univention.admin.uexceptions.permissionDenied – if the user does not have the required permissions.
univention.admin.uexceptions.ldapError – if the syntax of the DN is invalid.
univention.admin.uexceptions.ldapError – on any other LDAP error.
- ucsschool.importer.utils.ldap_connection.get_readonly_connection() Tuple[LoType, PoType][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() 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:
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: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookHook 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority = {'all_entries_read': None, 'entry_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:
- 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: univention.admin.uldap.access | None = None, dry_run: bool | None = False, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookHook 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority = {'pre_read': None}#
ucsschool.importer.utils.result_pyhook module#
Base class for all Python based Result-Pyhooks.
- class ucsschool.importer.utils.result_pyhook.ResultPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookHook 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority = {'user_result': None}#
- user_result(user_import_data: UserImportData) None[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#
Module to ease interactive use of import system.
ucsschool.importer.utils.test_user_creator module#
Class to create lots of test users.
ucsschool.importer.utils.user_pyhook module#
Base class for all Python based User hooks.
- class ucsschool.importer.utils.user_pyhook.UserPyHook(lo: univention.admin.uldap.access | None = None, dry_run: bool | None = None, *args: Any, **kwargs: Any)[source]#
Bases:
ImportPyHookBase 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_runis 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:
lo (univention.admin.uldap.access) – optional LDAP connection object
dry_run (bool) – whether hook is executed during a dry-run
- priority: Dict[str, int | None] = {'post_create': None, 'post_modify': None, 'post_move': None, 'post_remove': None, 'pre_create': None, 'pre_modify': None, 'pre_move': None, 'pre_remove': None}#
- pre_create(user: ImportUser) None[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: ImportUser) None[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().
- Do not run
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: ImportUser) None[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: ImportUser) None[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().
- Do not run
- 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: ImportUser) None[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: ImportUser) None[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().
- Do not run
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: ImportUser) None[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: ImportUser) None[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: str, value: int) None[source]#
Store a value for a new name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if a value is already stored to such a name
- modify(name: str, old_value: int, new_value: int) None[source]#
Store a value for an existing name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if no value is stored by that name
- retrieve(name: str) int[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
- class ucsschool.importer.utils.username_handler.LdapStorageBackend(attribute_storage_name: str, lo: univention.admin.uldap.access | None = None, pos: univention.admin.uldap.position | None = None)[source]#
Bases:
NameCounterStorageBackendPrior to using this class, a node must exist in LDAP: ‘cn=unique-<attribute_name>,cn=ucsschool,cn=univention,<base>’.
- create(name: str, value: int) None[source]#
Store a value for a new name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if a value is already stored to such a name
- modify(name: str, old_value: int, new_value: int) None[source]#
Store a value for an existing name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if no value is stored by that name
- retrieve(name: str) int[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
- class ucsschool.importer.utils.username_handler.MemoryStorageBackend(attribute_storage_name: str)[source]#
Bases:
NameCounterStorageBackend- create(name: str, value: int) None[source]#
Store a value for a new name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if a value is already stored to such a name
- modify(name: str, old_value: int, new_value: int) None[source]#
Store a value for an existing name.
- Parameters:
- Returns:
None
- Raises:
NameKeyExists – if no value is stored by that name
- retrieve(name: str) int[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
- class ucsschool.importer.utils.username_handler.UsernameHandler(max_length: int, dry_run: bool = 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'#
- get_storage_backend() NameCounterStorageBackend[source]#
- Returns:
NameCounterStorageBackend instance
- Return type:
- remove_bad_chars(name: str) str[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.
- format_name(name: str, max_length: int | None = None) str[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:
- Returns:
unique name
- Return type:
- Raises:
FormatError – if more than one counter variable was found in the scheme
- property counter_variable_to_function: Dict[str, Callable[[str], str]]#
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:
- class ucsschool.importer.utils.username_handler.EmailHandler(max_length: int = 254, dry_run: bool = True)[source]#
Bases:
UsernameHandlerCreate 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'#
- remove_bad_chars(name: str) str[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: str, max_length: int | None = None) str[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:
- Returns:
unique name
- Return type:
- Raises:
FormatError – if more than one counter variable was found in the scheme