# HG changeset patch # User ymh # Date 1496937477 -7200 # Node ID 3b39995505089143f09a9ccd7ba5e2e0a27070a7 # Parent 4c3ae065f22c4be6c5d110e7fbb22eb573d95b6a first data model for backend diff -r 4c3ae065f22c -r 3b3999550508 .hgignore --- a/.hgignore Thu Jun 08 14:46:34 2017 +0200 +++ b/.hgignore Thu Jun 08 17:57:57 2017 +0200 @@ -24,3 +24,11 @@ \.swo$ \.swp$ \.orig$ + +^src/.env$ +^src/run/ +^src/dist/ +^src/.vscode/ +^src/MANIFEST.in +^src/MANIFEST +^src/irinotes.egg-info/ diff -r 4c3ae065f22c -r 3b3999550508 src/.env.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/.env.tmpl Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,37 @@ +# Base url for the application. default='' +BASE_URL= + +# base url for static resources (ends with "/") +# default : /static/ +STATIC_URL=/static/ + +# The absolute path to the directory where collectstatic will collect static files for deployment. (https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-STATIC_ROOT) +# default: /run/web/static +STATIC_ROOT= + +# Absolute filesystem path to the directory that will hold user-uploaded files (https://docs.djangoproject.com/en/1.11/ref/settings/#media-root) +# default: /run/web/media +MEDIA_ROOT= + +# Secret key for the application. cf. https://docs.djangoproject.com/en/1.11/ref/settings/#secret-key +SECRET_KEY=ARANDOMSECRETKEY + +# Debug the application. Default True +DEBUG= + +# Comma separated values of authorized host. cf. https://docs.djangoproject.com/en/1.11/ref/settings/#allowed-hosts +# default: empty +ALLOWED_HOSTS=127.0.0.1,localhost + +# 12factor inspired DATABASE_URL environment variable cf.https://github.com/kennethreitz/dj-database-url +# examples: postgres://:@:/ +# examples: sqlite:////full/path/to/your/database/file.sqlite +# default: sqlite:////run/db/db.sqlite3 +DATABASE_URL=sqlite:////run/db/db.sqlite3 + +# path for the log file +# default: /run/log/log.txt +LOG_FILE= + +# log level one of CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET. Default: ERROR +LOG_LEVEL=DEBUG diff -r 4c3ae065f22c -r 3b3999550508 src/.pylintrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/.pylintrc Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,425 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[BASIC] + +# Naming hint for argument names +argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct argument names +argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for attribute names +attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct attribute names +attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=30 + +# Naming hint for function names +function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct function names +function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for method names +method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct method names +method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming hint for variable names +variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,future.builtins + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff -r 4c3ae065f22c -r 3b3999550508 src/CHANGE diff -r 4c3ae065f22c -r 3b3999550508 src/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/LICENSE Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,520 @@ +Copyright (c) 2016, IRI (Institute d Recherche de d'Innovation) +All rights reserved. + + + + +CeCILL-B FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat à l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +This Agreement is an open source software license intended to give users +significant freedom to modify and redistribute the software licensed +hereunder. + +The exercising of this freedom is conditional upon a strong obligation +of giving credits for everybody that distributes a software +incorporating a software ruled by the current license so as all +contributions to be properly identified and acknowledged. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Contribution: means any or all modifications, corrections, translations, +adaptations and/or new functions integrated into the Software by any or +all Contributors, as well as any or all Internal Modules. + +Module: means a set of sources files including their documentation that +enables supplementary functions or services in addition to those offered +by the Software. + +External Module: means any or all Modules, not derived from the +Software, so that this Module and the Software run in separate address +spaces, with one calling the other when they are run. + +Internal Module: means any or all Module, connected to the Software so +that they both execute in the same address space. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS + +The right to make Contributions includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. + +The Licensee is authorized to make any or all Contributions to the +Software provided that it includes an explicit notice that it is the +author of said Contribution and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows effective access to the full Source +Code of the Software at a minimum during the entire period of its +distribution of the Software, it being understood that the additional +cost of acquiring the Source Code shall not exceed the cost of +transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +If the Licensee makes any Contribution to the Software, the resulting +Modified Software may be distributed under a license agreement other +than this Agreement subject to compliance with the provisions of Article +5.3.4. + + + 5.3.3 DISTRIBUTION OF EXTERNAL MODULES + +When the Licensee has developed an External Module, the terms and +conditions of this Agreement do not apply to said External Module, that +may be distributed under a separate license agreement. + + + 5.3.4 CREDITS + +Any Licensee who may distribute a Modified Software hereby expressly +agrees to: + + 1. indicate in the related documentation that it is based on the + Software licensed hereunder, and reproduce the intellectual + property notice for the Software, + + 2. ensure that written indications of the Software intended use, + intellectual property notice and license hereunder are included in + easily accessible format from the Modified Software interface, + + 3. mention, on a freely accessible website describing the Modified + Software, at least throughout the distribution term thereof, that + it is based on the Software licensed hereunder, and reproduce the + Software intellectual property notice, + + 4. where it is distributed to a third party that may distribute a + Modified Software without having to make its source code + available, make its best efforts to ensure that said third party + agrees to comply with the obligations set forth in this Article . + +If the Software, whether or not modified, is distributed with an +External Module designed for use in connection with the Software, the +Licensee shall submit said External Module to the foregoing obligations. + + + 5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES + +Where a Modified Software contains a Contribution subject to the CeCILL +license, the provisions set forth in Article 5.3.4 shall be optional. + +A Modified Software may be distributed under the CeCILL-C license. In +such a case the provisions set forth in Article 5.3.4 shall be optional. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE CONTRIBUTIONS + +The Licensee who develops a Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE EXTERNAL MODULES + +The Licensee who develops an External Module is the owner of the +intellectual property rights over this External Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution. + + + 6.4 JOINT PROVISIONS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis-à-vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 1.0 dated 2006-09-05. diff -r 4c3ae065f22c -r 3b3999550508 src/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/README Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,41 @@ +# IRINOTES backoffice + +Back office for the IRINOTES application + +## Installation + +Please follow the command below to bootstrap the project + +```shell +$ mkdir -p run/{db,log,web} +$ mkdir -p run/web/{media,static} +$ cp .env.tmpl .env +$ vi .env +$ mkvirtualenv irinotes +$ pip install requirements/dev.txt +$ python manage.py migrate +$ python manage.py collectstatic +$ python manage.py createsuperuser +$ python manage.py runserver + +``` + +You can now visit the following url in your browser . + +Admin interface is at + +## Usage + +TODO: Write usage instructions + +## History + +TODO: Write history + +## Credits + +TODO: Write credits + +## License + +TODO: Write license diff -r 4c3ae065f22c -r 3b3999550508 src/irinotes/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irinotes/__init__.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,48 @@ +VERSION = (0, 0, 1, "final", 0) + +VERSION_STR = ".".join(map(lambda i:"%02d" % (i,), VERSION[:2])) + +### +# https://github.com/django/django/blob/1.9.1/django/utils/version.py +# +def get_version(version=None): + "Returns a PEP 440-compliant version number from VERSION." + if not version: + version = VERSION + version = get_complete_version(version) + + # Now build the two parts of the version number: + # main = X.Y[.Z] + # sub = .devN - for pre-alpha releases + # | {a|b|rc}N - for alpha, beta, and rc releases + + main = get_main_version(version) + + sub = '' + if version[3] == 'alpha' and version[4] == 0: + sub = '.dev' + + elif version[3] != 'final': + mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'rc'} + sub = mapping[version[3]] + str(version[4]) + + return str(main + sub) + +def get_complete_version(version): + """ + then checks for correctness of the tuple provided. + """ + assert len(version) == 5 + assert version[3] in ('alpha', 'beta', 'rc', 'final') + + return version + +def get_main_version(version=None): + "Returns main version (X.Y[.Z]) from VERSION." + version = get_complete_version(version) + parts = 2 if version[2] == 0 else 3 + return '.'.join(str(x) for x in version[:parts]) + +__version__ = get_version(VERSION) + +default_app_config = 'irinotes.apps.IriNotesConfig' diff -r 4c3ae065f22c -r 3b3999550508 src/irinotes/apps.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irinotes/apps.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,5 @@ +from django.apps import AppConfig + +class IriNotesConfig(AppConfig): + name = 'irinotes' + verbose_name = "IRI Notes app" diff -r 4c3ae065f22c -r 3b3999550508 src/irinotes/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irinotes/settings.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,189 @@ +""" +Django settings for irinotes project. + +Generated by 'django-admin startproject' using Django 1.11.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import logging + +from decouple import Csv, config +from dj_database_url import parse as db_url +from unipath import Path + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = Path(__file__).parent + +RUN_DIR = BASE_DIR.parent.child('run') + +STATIC_ROOT = config('STATIC_ROOT', default=RUN_DIR.child('web').child('static')) +MEDIA_ROOT = config('MEDIA_ROOT', default=RUN_DIR.child('web').child('media')) + +# base url +BASE_URL = config('BASE_URL', default='') + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = config('SECRET_KEY', '@povoyn_1_3dhfjktisno5l_0)_l1+m8$&mr8r2-srvd+m-58d') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = config('DEBUG', default=True, cast=bool) + +ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='', cast=Csv()) + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'colorful', + 'concurrency', + 'notes' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'irinotes.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'irinotes.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': config( + 'DATABASE_URL', + default='sqlite:///' + RUN_DIR.child('db').child('db.sqlite3'), + cast=db_url + ) +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +AUTH_USER_MODEL = 'notes.User' + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = config('STATIC_URL', default=BASE_URL + '/static/') + +# Logger + +LOG_FILE = config('LOG_FILE', default=RUN_DIR.child('log').child('log.txt')) +LOG_LEVEL = config('LOG_LEVEL', default=logging.DEBUG, cast=lambda l: logging.getLevelName(l)) + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': True, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'formatters' : { + 'simple' : { + 'format': "%(asctime)s - %(levelname)s : %(message)s", + }, + 'semi-verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s %(message)s' + }, + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + }, + 'stream_to_console': { + 'level': LOG_LEVEL, + 'class': 'logging.StreamHandler' + }, + 'file': { + 'level': LOG_LEVEL, + 'class': 'logging.FileHandler', + 'filename': LOG_FILE, + 'formatter': 'semi-verbose', + }, + }, + 'loggers': { + 'django.request': { + 'handlers': ['file'], + 'level': LOG_LEVEL, + 'propagate': True, + }, + 'irinotes': { + 'handlers': ['file'], + 'level': LOG_LEVEL, + 'propagate': True, + }, + } +} diff -r 4c3ae065f22c -r 3b3999550508 src/irinotes/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irinotes/urls.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,21 @@ +"""irinotes URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] diff -r 4c3ae065f22c -r 3b3999550508 src/irinotes/wsgi.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irinotes/wsgi.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,16 @@ +""" +WSGI config for irinotes project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "irinotes.settings") + +application = get_wsgi_application() diff -r 4c3ae065f22c -r 3b3999550508 src/manage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/manage.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "irinotes.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff -r 4c3ae065f22c -r 3b3999550508 src/notes/__init__.py diff -r 4c3ae065f22c -r 3b3999550508 src/notes/admin/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/admin/__init__.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,22 @@ +""" +Admin registrations +""" +from django.contrib import admin +from django.contrib.auth.models import Group + +from ..models import User, Note, Session, Protocol, Category +from .auth import UserAdmin +from .auth import GroupAdmin + + +# Re-register UserAdmin +admin.site.register(User, UserAdmin) + +# Re-register GroupAdmin +admin.site.unregister(Group) +admin.site.register(Group, GroupAdmin) + +admin.site.register(Note) +admin.site.register(Session) +admin.site.register(Protocol) +admin.site.register(Category) diff -r 4c3ae065f22c -r 3b3999550508 src/notes/admin/auth.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/admin/auth.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,25 @@ +from django.contrib import admin +from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin +from django.contrib.auth.admin import UserAdmin as BaseUserAdmin + +from notes.models import GroupProfile, UserProfile + + +# Define an inline admin descriptor for Employee model +# which acts a bit like a singleton +class UserProfileInline(admin.StackedInline): + model = UserProfile + can_delete = False + +# Define a new User admin +class UserAdmin(BaseUserAdmin): + inlines = (UserProfileInline, ) + + +class GroupProfileInline(admin.StackedInline): + model = GroupProfile + can_delete = False + + +class GroupAdmin(BaseGroupAdmin): + inlines = (GroupProfileInline, ) diff -r 4c3ae065f22c -r 3b3999550508 src/notes/apps.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/apps.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class NotesConfig(AppConfig): + name = 'notes' diff -r 4c3ae065f22c -r 3b3999550508 src/notes/locale/en/LC_MESSAGES/django.mo Binary file src/notes/locale/en/LC_MESSAGES/django.mo has changed diff -r 4c3ae065f22c -r 3b3999550508 src/notes/locale/en/LC_MESSAGES/django.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/locale/en/LC_MESSAGES/django.po Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,157 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-08 15:29+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: models/auth.py:11 +msgid "User" +msgstr "User" + +#: models/auth.py:12 +msgid "Users" +msgstr "Users" + +#: models/auth.py:17 +msgid "UserProfile" +msgstr "User profile" + +#: models/auth.py:18 +msgid "UserProfiles" +msgstr "User profiles" + +#: models/auth.py:25 +msgid "GroupProfile" +msgstr "Group profile" + +#: models/auth.py:26 +msgid "GroupProfiles" +msgstr "Group profiles" + +#: models/base.py:18 +msgid "Model|created" +msgstr "created" + +#: models/base.py:19 +msgid "Model|updated" +msgstr "updated" + +#: models/base.py:20 +msgid "Model|ext_id" +msgstr "external id" + +#: models/base.py:21 +msgid "Model|version" +msgstr "version" + +#: models/category.py:13 +msgid "Protocol|title" +msgstr "title" + +#: models/category.py:16 +msgid "Protocol" +msgstr "Protocol" + +#: models/category.py:17 +msgid "Protocols" +msgstr "Protocols" + +#: models/category.py:22 +msgid "Category|title" +msgstr "title" + +#: models/category.py:23 +msgid "Category|color" +msgstr "color" + +#: models/category.py:24 +msgid "Category|need_comment" +msgstr "need comment" + +#: models/category.py:25 +msgid "Category|description" +msgstr "description" + +#: models/category.py:28 +msgid "Category|protocol" +msgstr "protocol" + +#: models/category.py:33 +msgid "Category" +msgstr "Category" + +#: models/category.py:34 +msgid "Categories" +msgstr "Categories" + +#: models/core.py:13 +msgid "Session" +msgstr "Session" + +#: models/core.py:14 +msgid "Sessions" +msgstr "Sessions" + +#: models/core.py:20 +msgid "Session|title" +msgstr "title" + +#: models/core.py:21 +msgid "Session|description" +msgstr "description" + +#: models/core.py:22 +msgid "Session|protocol" +msgstr "protocol" + +#: models/core.py:26 +msgid "Note" +msgstr "Note" + +#: models/core.py:27 +msgid "Notes" +msgstr "Notes" + +#: models/core.py:30 +msgid "Note|tc_start" +msgstr "start timecode" + +#: models/core.py:31 +msgid "Note|tc_end" +msgstr "end timeocde" + +#: models/core.py:32 +msgid "Note|session" +msgstr "session" + +#: models/core.py:33 +msgid "Note|text_plain" +msgstr "text plain" + +#: models/core.py:34 +msgid "Note|text_html" +msgstr "text html" + +#: models/core.py:35 +msgid "Note|text_raw" +msgstr "text raw" + +#: models/core.py:36 +msgid "Note|margin_note" +msgstr "margin note" + +#: models/core.py:37 +msgid "Note|categorization" +msgstr "categorization" diff -r 4c3ae065f22c -r 3b3999550508 src/notes/locale/fr/LC_MESSAGES/django.mo Binary file src/notes/locale/fr/LC_MESSAGES/django.mo has changed diff -r 4c3ae065f22c -r 3b3999550508 src/notes/locale/fr/LC_MESSAGES/django.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/locale/fr/LC_MESSAGES/django.po Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,158 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-08 15:29+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: models/auth.py:11 +msgid "User" +msgstr "Utilisateur" + +#: models/auth.py:12 +msgid "Users" +msgstr "Utilisateurs" + +#: models/auth.py:17 +msgid "UserProfile" +msgstr "Profil utilisateur" + +#: models/auth.py:18 +msgid "UserProfiles" +msgstr "Profils utilisateur" + +#: models/auth.py:25 +msgid "GroupProfile" +msgstr "Profile groupe" + +#: models/auth.py:26 +msgid "GroupProfiles" +msgstr "Profiles groupe" + +#: models/base.py:18 +msgid "Model|created" +msgstr "créé" + +#: models/base.py:19 +msgid "Model|updated" +msgstr "mis à jour" + +#: models/base.py:20 +msgid "Model|ext_id" +msgstr "identifiant externe" + +#: models/base.py:21 +msgid "Model|version" +msgstr "version" + +#: models/category.py:13 +msgid "Protocol|title" +msgstr "titre" + +#: models/category.py:16 +msgid "Protocol" +msgstr "Protocole" + +#: models/category.py:17 +msgid "Protocols" +msgstr "Protocoles" + +#: models/category.py:22 +msgid "Category|title" +msgstr "titre" + +#: models/category.py:23 +msgid "Category|color" +msgstr "couleur" + +#: models/category.py:24 +msgid "Category|need_comment" +msgstr "a un commentaire" + +#: models/category.py:25 +msgid "Category|description" +msgstr "description" + +#: models/category.py:28 +msgid "Category|protocol" +msgstr "protocole" + +#: models/category.py:33 +msgid "Category" +msgstr "Categorie" + +#: models/category.py:34 +msgid "Categories" +msgstr "Categories" + +#: models/core.py:13 +msgid "Session" +msgstr "Session" + +#: models/core.py:14 +msgid "Sessions" +msgstr "Sessions" + +#: models/core.py:20 +msgid "Session|title" +msgstr "titre" + +#: models/core.py:21 +msgid "Session|description" +msgstr "description" + +#: models/core.py:22 +msgid "Session|protocol" +msgstr "protocole" + +#: models/core.py:26 +msgid "Note" +msgstr "Note" + +#: models/core.py:27 +msgid "Notes" +msgstr "Notes" + +#: models/core.py:30 +msgid "Note|tc_start" +msgstr "timecode début" + +#: models/core.py:31 +msgid "Note|tc_end" +msgstr "timecode fin" + +#: models/core.py:32 +msgid "Note|session" +msgstr "session" + +#: models/core.py:33 +msgid "Note|text_plain" +msgstr "texte seul" + +#: models/core.py:34 +msgid "Note|text_html" +msgstr "texte html" + +#: models/core.py:35 +msgid "Note|text_raw" +msgstr "texte brut" + +#: models/core.py:36 +msgid "Note|margin_note" +msgstr "note de marge" + +#: models/core.py:37 +msgid "Note|categorization" +msgstr "catégorisation" diff -r 4c3ae065f22c -r 3b3999550508 src/notes/migrations/0001_initial.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/migrations/0001_initial.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.2 on 2017-06-08 15:10 +from __future__ import unicode_literals + +import concurrency.fields +from django.conf import settings +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'User', + 'verbose_name_plural': 'Users', + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='GroupProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.TextField(blank=True, null=True)), + ('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), + ], + options={ + 'verbose_name': 'GroupProfile', + 'verbose_name_plural': 'GroupProfiles', + }, + ), + migrations.CreateModel( + name='Note', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Model|created')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Model|updated')), + ('ext_id', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='Model|ext_id')), + ('version', concurrency.fields.AutoIncVersionField(default=1, help_text='record revision number', verbose_name='Model|version')), + ('tc_start', models.DateTimeField()), + ('tc_end', models.DateTimeField()), + ('text_plain', models.TextField(blank=True, null=True, verbose_name='Note|text_plain')), + ('text_html', models.TextField(blank=True, null=True, verbose_name='Note|text_html')), + ('text_raw', models.TextField(blank=True, null=True, verbose_name='Note|text_raw')), + ('margin_note', models.TextField(blank=True, null=True, verbose_name='Note|margin_note')), + ('categorization', models.TextField(blank=True, null=True, verbose_name='Note|categorization')), + ], + options={ + 'verbose_name': 'Note', + 'verbose_name_plural': 'Notes', + 'ordering': ['tc_start'], + }, + ), + migrations.CreateModel( + name='Session', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Model|created')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Model|updated')), + ('ext_id', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='Model|ext_id')), + ('version', concurrency.fields.AutoIncVersionField(default=1, help_text='record revision number', verbose_name='Model|version')), + ('title', models.TextField(blank=True, null=True, verbose_name='Session|title')), + ('description', models.TextField(blank=True, null=True, verbose_name='Session|description')), + ('protocol', models.TextField(blank=True, null=True, verbose_name='Session|protocol')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Session', + 'verbose_name_plural': 'Sessions', + }, + ), + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'UserProfile', + 'verbose_name_plural': 'UserProfiles', + }, + ), + migrations.AddField( + model_name='note', + name='session', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='notes.Session', verbose_name='Note|session'), + ), + ] diff -r 4c3ae065f22c -r 3b3999550508 src/notes/migrations/__init__.py diff -r 4c3ae065f22c -r 3b3999550508 src/notes/models/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/models/__init__.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,8 @@ +""" +Models for notes +""" +from .auth import User, UserProfile, GroupProfile +from .core import Note, Session +from .category import Protocol, Category + +__all__ = ["User", "UserProfile", "GroupProfile", "Note", "Session", "Protocol", "Category"] diff -r 4c3ae065f22c -r 3b3999550508 src/notes/models/auth.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/models/auth.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,27 @@ +""" +auth module that defines irinotes' users and group +""" +from django.contrib.auth.models import AbstractUser, Group +from django.db import models +from django.utils.translation import ugettext_lazy as _ + + +class User(AbstractUser): + class Meta: + verbose_name = _('User') + verbose_name_plural = _('Users') + +class UserProfile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + class Meta: + verbose_name = _('UserProfile') + verbose_name_plural = _('UserProfiles') + + +class GroupProfile(models.Model): + group = models.OneToOneField(Group, unique=True, on_delete=models.CASCADE) + description = models.TextField(null=True, blank=True) + class Meta: + verbose_name = _('GroupProfile') + verbose_name_plural = _('GroupProfiles') + diff -r 4c3ae065f22c -r 3b3999550508 src/notes/models/base.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/models/base.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,27 @@ +""" +base abstract models +""" +import uuid + +from concurrency.fields import AutoIncVersionField +from django.db import models +from django.utils.translation import ugettext_lazy as _ + + +class ModelManager(models.Manager): + def get_by_natural_key(self, ext_id): + return self.get(ext_id=ext_id) + +class Model(models.Model): + objects = ModelManager() + + created = models.DateTimeField(auto_now_add=True, verbose_name=_('Model|created')) + updated = models.DateTimeField(auto_now=True, verbose_name=_('Model|updated')) + ext_id = models.UUIDField(unique=True, default=uuid.uuid4, verbose_name=_('Model|ext_id')) + version = AutoIncVersionField(verbose_name=_('Model|version')) + + def natural_key(self): + return (self.ext_id, ) + + class Meta: + abstract = True diff -r 4c3ae065f22c -r 3b3999550508 src/notes/models/category.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/models/category.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,34 @@ +""" +models for metacategories and protocol +""" +from colorful.fields import RGBColorField +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from .base import Model +from .auth import GroupProfile + + +class Protocol(Model): + title = models.CharField(max_length=255, verbose_name=_('Protocol|title')) + group_profile = models.OneToOneField(GroupProfile, on_delete=models.CASCADE) + class Meta: + verbose_name = _('Protocol') + verbose_name_plural = _('Protocols') + + + +class Category(models.Model): + title = models.CharField(max_length=255, verbose_name=_('Category|title')) + color = RGBColorField(verbose_name=_('Category|color')) + need_comment = models.BooleanField(default=False, verbose_name=_('Category|need_comment')) + description = models.TextField(null=True, blank=True, verbose_name=_('Category|description')) + protocol = models.ForeignKey( + Protocol, + verbose_name=_('Category|protocol'), + related_name='categories', + on_delete=models.CASCADE + ) + class Meta: + verbose_name = _('Category') + verbose_name_plural = _('Categories') diff -r 4c3ae065f22c -r 3b3999550508 src/notes/models/core.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/models/core.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,38 @@ +""" +irinotes core module +""" +from django.conf import settings +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from .base import Model + + +class Session(Model): + class Meta: + verbose_name = _('Session') + verbose_name_plural = _('Sessions') + + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + ) + title = models.TextField(null=True, blank=True, verbose_name=_('Session|title')) + description = models.TextField(null=True, blank=True, verbose_name=_('Session|description')) + protocol = models.TextField(null=True, blank=True, verbose_name=_('Session|protocol')) + +class Note(Model): + class Meta: + verbose_name = _('Note') + verbose_name_plural = _('Notes') + ordering = ["tc_start"] + + tc_start = models.DateTimeField(verbose_name=_('Note|tc_start')) + tc_end = models.DateTimeField(verbose_name=_('Note|tc_end')) + session = models.ForeignKey(Session, on_delete=models.CASCADE, verbose_name=_('Note|session')) + text_plain = models.TextField(null=True, blank=True, verbose_name=_('Note|text_plain')) + text_html = models.TextField(null=True, blank=True, verbose_name=_('Note|text_html')) + text_raw = models.TextField(null=True, blank=True, verbose_name=_('Note|text_raw')) + margin_note = models.TextField(null=True, blank=True, verbose_name=_('Note|margin_note')) + categorization = models.TextField(null=True, blank=True, verbose_name=_('Note|categorization')) + diff -r 4c3ae065f22c -r 3b3999550508 src/notes/tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/tests.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff -r 4c3ae065f22c -r 3b3999550508 src/notes/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/notes/views.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff -r 4c3ae065f22c -r 3b3999550508 src/requirements/base.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/requirements/base.txt Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,11 @@ +dj-database-url==0.4.2 +Django==1.11.2 +django-colorful==1.2 +django-concurrency==1.3.2 +django-guardian==1.4.8 +djangorestframework==3.6.3 +irinotes==0.0.1 +python-decouple==3.0 +pytz==2017.2 +six==1.10.0 +Unipath==1.1 diff -r 4c3ae065f22c -r 3b3999550508 src/requirements/base.txt.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/requirements/base.txt.in Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,2 @@ +# must run "pip install -r base.txt.in" in src/requirements +-e .. diff -r 4c3ae065f22c -r 3b3999550508 src/requirements/dev.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/requirements/dev.txt Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,1 @@ +-r base.txt diff -r 4c3ae065f22c -r 3b3999550508 src/requirements/prod.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/requirements/prod.txt Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,4 @@ +-r base.txt +pylibmc +uWSGI +psycopg2 diff -r 4c3ae065f22c -r 3b3999550508 src/setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/setup.py Thu Jun 08 17:57:57 2017 +0200 @@ -0,0 +1,156 @@ +import os +try: + from setuptools import setup +except ImportError: + from distutils.core import setup +from distutils.command.install_data import install_data +from distutils.command.install import INSTALL_SCHEMES +import sys + + +class osx_install_data(install_data): + """ + On MacOS, the platform-specific lib dir is /System/Library/Framework/Python/.../ + which is wrong. Python 2.5 supplied with MacOS 10.5 has an Apple-specific fix + for this in distutils.command.install_data#306. It fixes install_lib but not + install_data, which is why we roll our own install_data class. + """ + + def finalize_options(self): + """ + By the time finalize_options is called, install.install_lib is set to the + fixed directory, so we set the installdir to install_lib. The + install_data class uses ('install_data', 'install_dir') instead. + """ + self.set_undefined_options('install', ('install_lib', 'install_dir')) + install_data.finalize_options(self) + +def fullsplit(path, result=None): + """ + Split a pathname into components (the opposite of os.path.join) in a + platform-neutral way. + """ + if result is None: + result = [] + head, tail = os.path.split(path) + if head == '': + return [tail] + result + if head == path: + return result + return fullsplit(head, [tail] + result) + + +def launch_setup(setup_script_name, setup_script_args): + """ + Start setup + """ + if sys.platform == "darwin": + cmdclasses = {'install_data': osx_install_data} + else: + cmdclasses = {'install_data': install_data} + + + root_dir = os.path.dirname(__file__) + if root_dir != '': + os.chdir(root_dir) + source_dirs = ['irinotes', 'notes'] + + version_variables = {} + try: + with open(os.path.join(source_dirs[0], "__init__.py")) as f: + code = compile(f.read(), "__init__.py", 'exec') + exec(code, version_variables) + except: + pass + + version = version_variables['__version__'] + + packages, data_files = [], [] + + for source_dir in source_dirs: + for dirpath, dirnames, filenames in os.walk(source_dir): + # Ignore dirnames that start with '.' + for i, dirname in enumerate(dirnames): + if dirname.startswith('.') or dirname.startswith('__pycache__'): del dirnames[i] + if '__init__.py' in filenames: + packages.append('.'.join(fullsplit(dirpath))) + elif filenames: + data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]]) + + + # Tell distutils to put the data_files in platform-specific installation + # locations. See here for an explanation: + # http://groups.google.com/group/comp.lang.python/browse_thread/thread/35ec7b2fed36eaec/2105ee4d9e8042cb + for scheme in INSTALL_SCHEMES.values(): + scheme['data'] = scheme['purelib'] + + # Small hack for working with bdist_wininst. + # See http://mail.python.org/pipermail/distutils-sig/2004-August/004134.html + if len(sys.argv) > 1 and sys.argv[1] == 'bdist_wininst': + for file_info in data_files: + file_info[0] = '\\PURELIB\\%s' % file_info[0] + + #write MANIFEST.in + + with open("MANIFEST.in", "w") as m: + m.write("include CHANGES\n") + m.write("include LICENSE\n") + m.write("include README\n") + m.write("include MANIFEST.in\n") + m.write("include requirements/base.txt\n") + m.write("include requirements/dev.txt\n") + m.write("include requirements/prod.txt\n") + for entry in data_files: + file_list = entry[1] + for filename in file_list: + m.write("include %s\n" % (filename)) + + long_description = '' + with open('README', 'r') as f: + long_description = f.read() + + setup( + script_name=setup_script_name, + script_args=setup_script_args, + name='irinotes', + version=version, + author='IRI', + author_email='contact@iri.centrepompidou.fr', + packages=packages, + data_files=data_files, + cmdclass=cmdclasses, + scripts=[], + url='http://www.iri.centrepompidou.fr/dev/hg/irinotes', + license='CECILL-C', + description='projet Irinotes', + long_description=long_description, + classifiers=[ + 'Development Status :: 4 - Beta', + 'Environment :: Web Environment', + 'Framework :: Django', + 'Intended Audience :: Developers', + 'License :: Ceccil-B', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Utilities' + ], + install_requires=[ + "Django >= 1.11", + "python-decouple", + "Unipath", + "dj-database-url", + "six", + "djangorestframework >= 3.6", + "django-guardian >= 1.4", + "django-colorful", + "django-concurrency" + ], + ) + + +if __name__ == "__main__": + + script_name = os.path.basename(sys.argv[0]) + script_args = sys.argv[1:] + + launch_setup(script_name, script_args)