Module collectives.utils#

Module collectives.utils.access#

Decorators to help manage page access.

Knowledge of python decorator is usefull to understand this module. The documentation will not cover this subject, however, there is a lot of information about decorator on Internet.

See functools

collectives.utils.access.access_requires(function, test, api=False)#

Decorator to do a test before granting access

It is a very generic decorator meant to have a way to create any test to grant access to an endpoint

Parameters
  • f (function) – The function of the endpoint that will be protected

  • api (bool) – If True and access is denied, trigger a 403. Otherwise return an error message

  • test (function) – A function the must return a boolean. If false, access to f will be refused

Returns

the protected (decorated) f function

Return type

function

collectives.utils.access.confidentiality_agreement(api=False)#

Decorator which check if user has signed confidentiality agreement.

If in api mode, a failure will returns a 403 HTTP code. Else, it will redirect with a error flash message.

Parameters

api (function) – API mode

Returns

the protected (decorated) f function

Return type

function

collectives.utils.access.payments_enabled(api=False)#

Decorator which checks whether the payment functionnality is enabled

Parameters

api (bool) – If True and access is denied, trigger a 403. Otherwise return an error message

Returns

the protected (decorated) f function

Return type

function

collectives.utils.access.technician_required_f()#

Function to limit access to technician only.

collectives.utils.access.user_is(methods, api=False, **kwargs)#

Decorator which check if an user method to authorize access.

Example:

@user_is('is_admin')
@blueprint.route("/", methods=["GET", "POST"])
def administration():
    pass
Parameters
  • api (bool) – If True and access is denied, trigger a 403. Otherwise return an error message

  • methods (list or string) – the user methods to call. WARNING: this parameter should always be a constant (no user generated data). Can be a list, in which case, user is authorized if method returns True (ie if user has at least one of the listed roles)

Returns

the protected (decorated) f function

Return type

function

collectives.utils.access.valid_user(api=False)#

Decorator which check if user is logged in and has signed current legal text.

Parameters

api (bool) – If True and access is denied, trigger a 403. Otherwise return an error message

Returns

the protected (decorated) f function

Return type

function

Module collectives.utils.csv#

Module to handle csv import

collectives.utils.csv.csv_to_events(stream, description)#

Decode the csv stream to populate events.

Parameters
  • stream (io.StringIO) – the csv file as a stream.

  • description (String) – Description template that will be used to generate new events description.

Returns

The new events, the number of processed events, and the number of failed attempts

Return type

list(collectives.models.event.Event), int, int

collectives.utils.csv.fill_from_csv(event, row, template)#

Fill an Event object attributes with parameter from a csv row.

Parameters
  • event (collectives.models.event.Event) – The evet object to populate.

  • row (list(string)) – List of value from a csv file row

  • template (string) – Template for the event description. It can contains placeholders.

Returns

Nothing

collectives.utils.csv.parse(row, column_name)#

Parse a column value in csv format to an object depending on column type. Raise an exception if field is mandatory and is not set

Parameters
  • row (list(string)) – List of value from a csv file row

  • column_name (string) – Column name

Returns

The parsed value

collectives.utils.csv.process_stream(base_stream, activity_type, description)#

Creates the events from a csv file.

Processing will first try to process it as an UTF8 encoded file. If it fails on a decoding error, it will try as Windows encoding (iso-8859-1).

Parameters
  • base_stream (io.StringIO) – the csv file as a stream.

  • activity_type (collectives.models.activity_type.ActivityType) – The type of activity of the new events.

  • description (String) – Description template that will be used to generate new events description.

Returns

The number of processed events, and the number of failed attempts

Return type

(int, int)

Module collectives.utils.error#

Module to handle HTTP errors

collectives.utils.error.not_found(ex)#

If URL is unknown, redirect client or/and display an error message.

Parameters

e – exception which generated the error page

Returns

a redirection to index page

collectives.utils.error.server_error(ex)#

Return a very simple error page.

Note: in collectives, this function is only active in non debug mode.

Parameters

e – exception which generated the error page

Returns

error.html page with a 500 error code

Module collectives.utils.extranet#

Module to handle connexions to FFCAM extranet.

class collectives.utils.extranet.ExtranetApi#

SOAP Client to retrieve information from FFCAM servers.

app = None#

Current flask application.

Type

flask.Flask

auth_info = None#

Authentication information to connect to SOAP server.

Type

dictionnary

check_license(license_number)#

Get information on a license from FFCAM server.

Parameters

license_number (string) – License to get information about.

Returns

Licence information

Return type

LicenseInfo

disabled()#

Check if soap client has been initialized.

If soap client has not been initialized, it means we are in dev mode.

Returns

True if ExtranetApi is disabled.

Return type

boolean

fetch_user_info(license_number)#

Get user information on a license from FFCAM server.

Parameters

license_number (string) – User license to get information about.

Returns

Licence information, or None in case of API error

Return type

UserInfo

init()#

Initialize the SOAP Client using app config

init_app(app)#

Initialize the extranet with the app.

Parameters

app (flask.Flask) – Current app.

soap_client = None#

SOAP client object user to connect to FFCAM client.

Type

zeep.Client

exception collectives.utils.extranet.ExtranetError#

An exception indicating that something has gone wrong with extranet API

collectives.utils.extranet.LICENSE_EXPIRY_MONTH = 10#

Month of license end.

Type

int

collectives.utils.extranet.LICENSE_RENEWAL_MONTH = 9#

Month of license start.

If a license has been renewed after RENEWAL_MONTH of year Y, then it is valid until EXPIRY_MONTH of year Y+1; else it is only valid until EXPITY_MONTH of year Y.

Type

int

class collectives.utils.extranet.LicenseInfo#

Licence information as retrieved from FFCAM servers.

exists = False#

If licence exists. :type: boolean

expiry_date()#

Get licence expiration date.

Licence expire at the start of the month LICENSE_EXPIRY_MONTH which follow the renewal date.

Returns

License expiration date. None if renewal_date is None

Return type

datetime.date

is_valid_at_time(time)#

Check if license is valid at a given date.

Parameters

time (datetime.date) – Date to test license validity.

Returns

True if license is valid

Return type

boolean

renewal_date = None#

Date of renewal of the licence.

Type

datetime.date

class collectives.utils.extranet.UserInfo#

User information as retrieved from FFCAM servers.

date_of_birth = None#

User date of birth.

Type

datetime.date

email = ''#

User email.

Type

String

emergency_contact_name = ''#

User Emergency contact name.

Type

string

emergency_contact_phone = ''#

User Emergency contact phone.

Type

string

first_name = ''#

User first name.

Type

String

is_valid = False#

True if user exists on servers.

Type

boolean

last_name = ''#

User last name.

Type

String

license_category = ''#

User license category.

Type

string

phone = ''#

User phone.

Type

String

qualite = ''#

User title. “titre de civilité”.

Can be M Mme Mlle. Is used to guess gender.

Type

String

collectives.utils.extranet.api = <collectives.utils.extranet.ExtranetApi object>#

ExtranetApi object that will handle request to FFCAM servers.

api requires to be initialized with ExtranetApi.init_app() to be used.

Type

ExtranetApi

collectives.utils.extranet.sync_user(user, user_info, license_info)#

Populate a user object with user and license info from FFCAM servers.

Parameters

Module collectives.utils.init#

Module to initialise DB

collectives.utils.init.activity_types(app)#

Initialize activity types

Get activity types defined in Flask application configuration (ACTIVITY_TYPES) and load it in the database. This function should be called once at app initilisation. If DB is not available, it will print a warning in stdout.

Parameters

app – Application where to extract ACTIVITY_TYPES

Type

flask.Application

Returns

None

collectives.utils.init.catch_db_errors(fct, app, *args, **kwargs)#

Catches DB error in fct.

Usually, it is because the db is not already set up during DB setup. Thus, it is not very important.

Parameters

fct – the function that will be called.

collectives.utils.init.event_types(app)#

Initialize event types

Get event types defined in Flask application configuration (EVENT_TYPES) and load it in the database. This function should be called once at app initilisation. If DB is not available, it will print a warning in stdout.

Parameters

app – Application where to extract EVENT_TYPES

Type

flask.Application

Returns

None

collectives.utils.init.init_admin(app)#

Create an admin account if it does not exists. Enforce its password.

Password is config:ADMINPWD

collectives.utils.init.init_config(app, force=False, path='collectives/configuration.yaml', clean=True)#

Load configuration items at app creation.

Parameters
  • app – Flask app used for configuration

  • force (bool) – If true, force content update. Default false

  • path (str) – Path to YAML configuration list

  • clean (bool) – If True, remove configuration which is not present in the file

collectives.utils.init.is_running_migration() bool#

Detects whether we are running a migration command.

Returns

True if running a migration

collectives.utils.init.is_running_migration_context(ctx) bool#

Detects whether we are running a migration command.

It has not error protection if there is no context.

Parameters

ctx (cli.Context) – The current click context

Returns

True if running a migration

collectives.utils.init.populate_db(app)#

Populates the database with admin account and activities, if and only if we’re not currently running a db migration command

Parameters

app (flask.Application) – The Flask application

Module collectives.utils.jinja#

Helpers functions that are make available to Jinja.

This module should not contains other functions than helpers_processors()

collectives.utils.jinja.helpers_processor()#

Function used by Jinja to access utils fonctions.

Returns

Dictionnary of collectives.utils.time functions.

Return type

dict(Function)

collectives.utils.jinja.map_method(function, iterable) list#

Map an iterable to one of its method

Parameters
  • function (string) – The function name

  • function – The interable

Returns

the result of the iterable method

Convert a git version to an http link.

Meanwhile, it also sanitize the version since it will be included as html in the page.

Parameters

version (string) – The version as a git describe format.

Returns

HTML string a the version wih its links.

Return type

string

Module collectives.utils.mail#

Module to handle mail

This module handles mail sending using a SMTP server. Also, it can sign with DKIM. Conf are taken from app config:

  • config.SMTP_HOST: Hostname of SMTP server

  • config.SMTP_PORT: Connexion port to SMTP server

  • config.SMTP_ADDRESS: Sender address. Also used to set DKIM domain

  • config.SMTP_LOGIN: Login of SMTP server

  • config.SMTP_PASSWORD: Password of SMTP server

  • config.DKIM_SELECTOR: DKIM selector, usually default

  • config.DKIM_KEY: DKIM private key as PEM format

collectives.utils.mail.send_mail(**kwargs)#

Wrapper for send_mail_threaded()

collectives.utils.mail.send_mail_threaded(app, **kwargs)#

Send a mail.

Usage example:

send_mail(subject="test", email="user@example.org", message="TEST")

If email is a list, mails are sent as Cci.

Parameters

**kwargs – See below

Keyword Arguments
  • subject (string) – Email subject

  • email (string or list(string)) – Email Adress recipient

  • message (string) – Email body

  • error_action (function) – Function to activate if email sending fails

  • success_action (string) – Function to activate if email sending succeeds

Module collectives.utils.misc#

Miscellaneous utils functions

class collectives.utils.misc.NoDefault#

Dummy Class to know if default has been set in deepgetattr()

collectives.utils.misc.deepgetattr(obj, attr, default=<collectives.utils.misc.NoDefault object>)#

Recurses through an attribute chain to get the ultimate value.

Example: deepgetattr(role, ‘user.first_name’)

Parameters
  • obj – The Object to get attribute from

  • attr (String) – The attribute to get. Use dots to get attribute of an attribute

  • default (Object) – Optionnal. If no attribute is found, return this value. If default is not defined, throw an exception

Returns

the selected attribute

Return type

Object

collectives.utils.misc.is_mobile_user()#

Read browser user agent from the request and return True if a mobile browser is detected

collectives.utils.misc.sanitize_file_name(name: str) str#

Returns sanitized filename without characters that cannot be in a filename.

Basically removes all characters not alphanumerical, space, accentuated character, simple quote, dot, dash, commas, and underscore.

collectives.utils.misc.to_ascii(value)#

Convert an unicode string to ASCII, drop characters that can’t be converted

Parameters

value (str) – Input string

Returns

ASCII string

Return type

str

collectives.utils.misc.truncate(value: str, max_len: int, append_ellipsis: bool = True) str#

Truncates a string so that it is no longer that a predefined length

Parameters
  • value – string to truncate

  • max_len – maximum length of returned string

  • append_ellipsis – whether to put an ellipsis at the end of the string when it is truncated

Returns

the truncated string

Module collectives.utils.numbers#

Module for formatting number and currencies

collectives.utils.numbers.check_phone(number: str) bool#
Returns

True if the number if a real phone number

collectives.utils.numbers.format_bytes(size)#

Formats a size in bytes to human-readable units

Parameters

size (int) – The size in bytes

Returns

A string representing the amount in human-readable form, e.g. ko, Go

Return type

string

collectives.utils.numbers.format_currency(amount)#

Formats a decimal amount in euros following the french locale

Parameters

amount (decimal.Decimal) – The amount to be formatted

Returns

A string representing the amount in french locale, like “1,345.67 €”

Return type

string

collectives.utils.numbers.format_phones(phone_str: str) str#
Returns

a regurlarly formed phone number, with proper spacing.

Parameters

phone – A phone number

Module collectives.utils.payline#

Module to handle connexions to Payline.

class collectives.utils.payline.BuyerInfo(user=None)#

Information about the user making the payment

birth_date = ''#

Data of birth, ptional

Type

string

email = ''#

Email address, must be valid

Type

string

first_name = ''#

Buyer first name

Type

string

last_name = ''#

Buyer last name

Type

string

title = ''#

Title, e.g. ‘M.’, ‘Mme.’, etc

Type

string

class collectives.utils.payline.OrderInfo(payment=None)#

Class describing an order for a payment request. Will usually be constructed from a collectives.models.payment.Payment object

amount_in_cents = 0#

Amount in smallest currency unit (e.g euro cents)

Type

int

date = '01/01/1970 13:25'#

Date and time at which the order is being made, with format dd/mm/YYYY HH:MM

Type

string

details = {}#

Dictionary containing details about the order See https://docs.payline.com/display/DT/Object+-+orderDetail

Type

dict

metadata = {}#

Dictionnary containing free-form metadata about the order. Used in lieu of details as Payline does not seem to acknowledge orderDetails

Type

dict

payment = None#

Related database Payment entry

Type

collectives.models.payment.Payment

private_data()#
Returns

Metadata in the Payline key-value list format

Return type

dict

unique_ref()#
Returns

An unique reference for the order

Return type

string

collectives.utils.payline.PAYLINE_VERSION = 26#

Version of payline API :type: int

collectives.utils.payline.PAYMENT_ACTION = 101#

Payment action, as per https://docs.payline.com/display/DT/Codes+-+Action 101 stand for “Authorization and Capture”

Type

int

collectives.utils.payline.PAYMENT_MODE = 'CPT'#

Payment mode, as per https://docs.payline.com/display/DT/Codes+-+Mode CPT stands for “Full”

Type

string

class collectives.utils.payline.PaylineApi#

SOAP Client to process payment with payline, refer to Payline docs

app = None#

Current flask application.

Type

flask.Flask

directpayment_client = None#

SOAP client object to connect to Payline DirectPaymentAPI.

Type

pysimplesoap.client.SoapClient

disabled()#

Check if soap client has been initialized.

If soap client has not been initialized, it means we are in dev mode.

Returns

True if PaylineApi is disabled.

Return type

boolean

do_refund(payment_details)#

Tries to refund a previously approved online payment.

Will first try a ‘reset’ call (cancel immediately the payment if it has not been debited yet), and if this fail will try a full ‘refund’ call.

Parameters

payment_details – The payment details as returned by getWebPaymentDetails()

Returns

An object representing the response details, or None if the API call failed

Return type

collectives.utils.payline.RefundDetails

do_web_payment(order_info, buyer_info)#

Initiates a payment request with Payline and returns the resulting token identifier on success, or information about the error

Parameters
Returns

An object representing the API response, or None if the API call failed

Return type

collectives.utils.payline.PaymentRequest

encoded_auth = ''#

authentication string for http http_header

Type

string

get_web_payment_details(token)#

Returns the details about a payment that has been previously initiated

Parameters

token (string) – The unique identifer returned by the do_web_payment() call

Returns

An object representing the payment details, or None if the API call failed

Return type

collectives.utils.payline.PaymentDetails

init()#

Initialize the SOAP Client using app config.

init_app(app)#

Initialize the payline with the app.

Parameters

app (flask.Flask) – Current app.

payline_access_key = ''#

Payline access key (to be set in payline backoffice)

Type

string

payline_contract_number = ''#

payline contract number

Type

string

payline_country = ''#

Payline country code

Type

string

payline_currency = ''#

payment currency : euro = 978

Type

string

payline_merchant_id = ''#

Payline merchant id refer to payline account

Type

string

payline_merchant_name = ''#

Payline merchant name

Type

string

webpayment_client = None#

SOAP client object to connect to Payline WebPaymentAPI.

Type

pysimplesoap.client.SoapClient

class collectives.utils.payline.PaymentDetails(response)#

Class wrapping the results of a “get payment details” API request

amount()#
Returns

The payment amount in decimal currency units

Return type

decimal.Decimal

property authorization#
Returns

The dictionary corresponding to the “authorization” par of the response

Return type

dict

static from_metadata(raw_metadata)#

Constructs a PaymentDetails object from a metadata string

Param

raw_metadata Json-encoded metadata string

Type

raw_metadata string

Returns

Payment details

Return type

collectives.utils.payline.PaymentDetails

property payment#

See https://docs.payline.com/display/DT/Object+-+payment

Returns

The dictionary corresponding to the “payment” par of the response

Return type

dict

raw_metadata()#
Returns

the raw response dictionary as a Json string

Return type

string

response = {'authorization': {}, 'payment': {}, 'transaction': {}}#

Dictionary containing the raw SOAP api response for a payment details query. See https://docs.payline.com/display/DT/Webservice+-+getWebPaymentDetailsResponse

Type

dict

result = <collectives.utils.payline.PaymentResult object>#

Whether the request has succeeded, or why it has not

Type

collectives.utils.payline.PaymentResult

property transaction#

See https://docs.payline.com/display/DT/Object+-+transaction

Returns

The dictionary corresponding to the “transaction” par of the response

Return type

dict

class collectives.utils.payline.PaymentRequest#

Response from a payment creation request

redirect_url = ''#

URL on which the shopper’s browser must be redirected to make the payment.

Type

string

result = <collectives.utils.payline.PaymentResult object>#

Whether the request has succeeded, or why it has not

Type

collectives.utils.payline.PaymentResult

token = ''#

Time stamped token that identifies the merchant’s web payment request

Type

string

class collectives.utils.payline.PaymentResult(response=None)#

Result returned after payline API requests. Gives information about whether the request has succeeded, or why it has not

code = ''#

Return code, see https://docs.payline.com/display/DT/Return+codes

Type

string

is_accepted()#

Checks whether the call was successful

Returns

True if successful (return message ‘ACCEPTED’), False for any other

Return type

bool

long_message = ''#

long message of transaction status details

Type

string

payment_status()#

Maps the API response short message and code to a value from our PaymentStatus enum.

Returns

The corresponding payment status

Return type

collectives.models.payment.PaymentStatus

short_message = ''#

short message of transaction status i.e. : ACCEPTED, REFUSED, ERROR… See https://docs.payline.com/display/DT/Codes+-+ShortMessage

Type

string

class collectives.utils.payline.RefundDetails(response)#

Class wrapping the results of a “do refund” API request

raw_metadata()#
Returns

the raw response dictionary as a Json string

Return type

string

response = {'transaction': {}}#

Dictionary containing the raw SOAP api response for a payment details query. See https://docs.payline.com/display/DT/Webservice+-+doRefundResponse

Type

dict

result = <collectives.utils.payline.PaymentResult object>#

Whether the request has succeeded, or why it has not

Type

collectives.utils.payline.PaymentResult

property transaction#

See https://docs.payline.com/display/DT/Object+-+transaction

Returns

The dictionary corresponding to the “transaction” par of the response

Return type

dict

collectives.utils.payline.api = <collectives.utils.payline.PaylineApi object>#

PaylineApi object that will handle request to Payline.

api requires to be initialized with PaylineApi.init_app() to be used.

Type

PaylineApi

Module collectives.utils.render_markdown#

Module handling Markdown rendering.

Markdown is mainly used in event description.

collectives.utils.render_markdown.markdown_to_html(text)#

Convert a markdown text to HTML, unless is already marked as markup-safe.

Parameters

text (String) – Markdown text.

Returns

Converted HTML text.

Return type

String

Module collectives.utils.time#

Module for time management and display.

collectives.utils.time.current_time()#

Return current time in the defined time zone.

See config.TZ_NAME

Datetimes are stored in naive format, assumed to always be in the correct timezone. For Python to be able to compare, dates must be stripped from the tz information from our local time

Returns

Current time

Return type

datetime.datetime

collectives.utils.time.format_date(value, short=False)#

Format a date. (eg “Samedi 16 février 2020”).

Parameters
  • value (datetime.datetime or datetime.date) – Date to format

  • short (bool) – If True, display a short version of the date as format_date_short()

Returns

Formatted date

Return type

string

collectives.utils.time.format_date_range(start, end, short=True)#

Format a range of dates without their time. (eg “Samedi 12 février 2018 au Dimanche 13 février 2018”).

Parameters
  • start (datetime.datetime or datetime.date) – Range start date.

  • end (datetime.datetime or datetime.date) – Range end date.

  • short (bool) – If True, display short version of the dates as format_date_short()

Returns

Formatted date range.

Return type

string

collectives.utils.time.format_date_short(value)#

Format a date. (eg “Sam 16 février”).

Parameters

value (datetime.datetime or datetime.date) – Date to format

Returns

Formatted date

Return type

string

collectives.utils.time.format_datetime(value)#

Format a date + time. (eg “Samedi 16 février 2020 à 8h00”).

Parameters

value (datetime.datetime) – Date to format

Returns

Formatted date or ‘N/A’ if value is None

Return type

string

collectives.utils.time.format_datetime_range(start, end)#

Format a range of dates. (eg “Samedi 12 février 2018 à 08:00 au Dimanche 13 février 2018 à 15:00”).

  • If start and end are the same day, day is not repeated.

  • If start and end are the same, it is not treated as a range.

  • If start and end are at 0h00, time is not formatted.

Parameters
  • start (datetime.datetime) – Range start date.

  • end (datetime.datetime) – Range end date.

Returns

Formatted date range.

Return type

string

collectives.utils.time.format_time(value)#

Format a time. (eg “8h12”).

Parameters

value (datetime.datetime) – Date to format

Returns

Formatted date

Return type

string

collectives.utils.time.fr_months = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre']#

Months in French.

Server may not have fr_FR locale installed, for convenience, we simply define months names here

collectives.utils.time.fr_short_months = ['jan.', 'fév.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sep.', 'oct.', 'nov.', 'déc.']#

Months abbreviations in French.

Server may not have fr_FR locale installed, for convenience, we simply define months abbreviations here

collectives.utils.time.fr_week_days = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']#

Day of week in French.

Server may not have fr_FR locale installed, for convenience, we simply define days of weeks names here

collectives.utils.time.server_local_time()#

Alias of current_time()

Module collectives.utils.url#

Module which contains various helping functions for url management.

collectives.utils.url.slugify(value)#

String normalisation.

Normalizes string, converts to lowercase, removes non-alpha characters, and converts spaces to hyphens.

From Django’s “django/template/defaultfilters.py”.