[DEV] first basic version

This commit is contained in:
Edouard DUPIN 2019-04-15 22:19:17 +02:00
parent 153fadd59f
commit 3051b451ba
11 changed files with 1878 additions and 0 deletions

373
LICENSE Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

1
MANIFEST.in Normal file
View File

@ -0,0 +1 @@
include README.rst

View File

@ -2,3 +2,117 @@ Lutin
=====
`qworktree` is a simple tool to permit to manage a qt worktree without managing the main xxx.pro.
It is designed to create the main pro file at the root path of the tree (where you execute it it.
It have some containts that I does not arrive to remove:
- need to declate the MK_FEATURE element
- generate 2 file in the root directory
.. image:: https://badge.fury.io/py/qworktree.png
:target: https://pypi.python.org/pypi/qworktree
Instructions
------------
This tool is to create the main .pro file of your worktree
qworktree is under a FREE license that can be found in the LICENSE file.
Any contribution is more than welcome ;)
git repository
--------------
http://github.com/HeeroYui/qworktree/
Installation
------------
Requirements: ``Python >= 2.7`` and ``pip``
Just run:
pip install qworktree
Install pip on debian/ubuntu:
sudo apt-get install pip
Install pip on ARCH-linux:
sudo pacman -S pip
Install pip on MacOs:
sudo easy_install pip
Usage
-----
Download your worktree and run the command
qworktree
export QMAKEFEATURES=`pwd`/mkfeatures
mkdir build
cd build
qmake ..
the qworktree will generate local files
folder_name.pro ==> the file of the worktree description
defines.prf ==> a file that define a list of dependency macro
Creating the needed elements
----------------------------
1: Need a mkfeature to add an include to determine the main root worktree: ```mkfeatures/root_directory.prf```
ROOT_DIRETORY += $${PWD}/..
ROOT_DEFINES += $${PWD}/../defines.prf
load(../defines.prf)
2: Create a file in your library/plugin/application folder: ```folderName/qworktree_folderName.py```
#!/usr/bin/python
# -*- coding: utf-8 -*-
depend_on = [
"depend_worktree_lib1_name",
"depend_worktree_lib2_name"
]
3: Create a file in your worktree with the dependency property: ```folderName/dependencies.pri```
INCLUDEPATH += $$PWD
LIBS *= -llibraryName
4: Import the library elements:
load(root_directory.prf)
# request include properties
include($$ROOT_DIRETORY/$$LIB_DECLARE_DEPENDENCIES_FOLDERNAME1)
include($$ROOT_DIRETORY/$$LIB_DECLARE_DEPENDENCIES_MYLIB2)
Note that the define is generate in the file ```defines.prf```
License (MPL v2.0)
------------------
Copyright qworktree Edouard DUPIN
Licensed under the Mozilla Public License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.mozilla.org/MPL/2.0/
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

11
bin/qworktree Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import qworktree

253
qworktree/__init__.py Executable file
View File

@ -0,0 +1,253 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import os
import sys
import fnmatch
import copy
# Local import
from . import tools
from . import debug
from . import env
from . import arguments
def filter_name_and_file(root, list_files, filter):
# filter elements:
tmp_list = fnmatch.filter(list_files, filter)
out = []
for elem in tmp_list:
if os.path.isfile(os.path.join(root, elem)) == True:
out.append(elem);
return out;
def filter_path(root, list_files):
out = []
for elem in list_files:
if len(elem) == 0 \
or elem[0] == '.':
continue
if os.path.isdir(os.path.join(root, elem)) == True:
out.append(elem);
return out;
def import_path_local(path, limit_sub_folder, exclude_path = [], base_name = ""):
out = []
debug.verbose("qworktree files: " + str(path) + " [START]")
if limit_sub_folder == 0:
debug.debug("Subparsing limitation append ...")
return []
list_files = os.listdir(path)
try:
list_files = os.listdir(path)
except:
# an error occure, maybe read error ...
debug.warning("error when getting subdirectory of '" + str(path) + "'")
return []
if path in exclude_path:
debug.debug("find '" + str(path) + "' in exclude_path=" + str(exclude_path))
return []
# filter elements:
tmp_list_qworktree_file = filter_name_and_file(path, list_files, base_name + "*.py")
debug.verbose("qworktree files: " + str(path) + " : " + str(tmp_list_qworktree_file))
# Import the module:
for filename in tmp_list_qworktree_file:
out.append(os.path.join(path, filename))
debug.extreme_verbose(" Find a file : '" + str(out[-1]) + "'")
need_parse_sub_folder = True
rm_value = -1
# check if we need to parse sub_folder
if len(tmp_list_qworktree_file) != 0:
need_parse_sub_folder = False
# check if the file "qworktree_parse_sub.py" is present ==> parse SubFolder (force and add +1 in the resursing
if base_name + "ParseSubFolders.txt" in list_files:
debug.debug("find SubParser ... " + str(base_name + "ParseSubFolders.txt") + " " + path)
data_file_sub = tools.file_read_data(os.path.join(path, base_name + "ParseSubFolders.txt"))
if data_file_sub == "":
debug.debug(" Empty file Load all subfolder in the worktree in '" + str(path) + "'")
need_parse_sub_folder = True
rm_value = 0
else:
list_sub = data_file_sub.split("\n")
debug.debug(" Parse selected folders " + str(list_sub) + " no parse local folder directory")
need_parse_sub_folder = False
for folder in list_sub:
if folder == "" \
or folder == "/":
continue;
tmp_out = import_path_local(os.path.join(path, folder),
1,
exclude_path,
base_name)
# add all the elements:
for elem in tmp_out:
out.append(elem)
if need_parse_sub_folder == True:
list_folders = filter_path(path, list_files)
for folder in list_folders:
tmp_out = import_path_local(os.path.join(path, folder),
limit_sub_folder - rm_value,
exclude_path,
base_name)
# add all the elements:
for elem in tmp_out:
out.append(elem)
return out
my_args = arguments.qworktreeArg()
my_args.add_section("option", "Can be set one time in all case")
my_args.add("h", "help", desc="Display this help")
my_args.add("v", "verbose", list=[["0","None"],["1","error"],["2","warning"],["3","info"],["4","debug"],["5","verbose"],["6","extreme_verbose"]], desc="display debug level (verbose) default =2")
my_args.add("c", "color", desc="Display message in color")
local_argument = my_args.parse()
##
## @brief Display the help of this makefile.
##
def usage():
color = debug.get_color_set()
# generic argument displayed :
my_args.display()
print(" Action availlable" )
print(" ex: " + sys.argv[0] + " -c init http://github.com/atria-soft/manifest.git")
print(" ex: " + sys.argv[0] + " sync")
exit(0)
def check_boolean(value):
if value == "" \
or value == "1" \
or value == "true" \
or value == "True" \
or value == True:
return True
return False
# preparse the argument to get the verbose element for debug mode
def parseGenericArg(argument, active):
debug.extreme_verbose("parse arg : " + argument.get_option_name() + " " + argument.get_arg() + " active=" + str(active))
if argument.get_option_name() == "help":
if active == False:
usage()
return True
elif argument.get_option_name()=="jobs":
if active == True:
#multiprocess.set_core_number(int(argument.get_arg()))
pass
return True
elif argument.get_option_name()=="depth":
if active == True:
env.set_parse_depth(int(argument.get_arg()))
return True
elif argument.get_option_name() == "verbose":
if active == True:
debug.set_level(int(argument.get_arg()))
return True
elif argument.get_option_name() == "color":
if active == True:
if check_boolean(argument.get_arg()) == True:
debug.enable_color()
else:
debug.disable_color()
return True
elif argument.get_option_name() == "no-fetch-manifest":
if active == False:
env.set_fetch_manifest(False)
return True
return False
# parse default unique argument:
for argument in local_argument:
parseGenericArg(argument, True)
__base_element_name = env.get_system_base_name() + "_"
tmp_out = import_path_local(tools.get_run_path(),
3,
[],
__base_element_name)
def get_element_name(_path):
base_name = os.path.basename(_path)
debug.verbose(" path: '" + _path + "' ==> basename='" + base_name + "'")
if len(base_name) <= 3 + len(__base_element_name):
# reject it, too small
return None
base_name = base_name[:-3]
if base_name[:len(__base_element_name)] != __base_element_name:
# reject it, wrong start file
return None
debug.verbose(" ==> '" + base_name[len(__base_element_name):] + "'")
return base_name[len(__base_element_name):]
def get_element_depend(_path):
sys.path.append(os.path.dirname(_path))
name = get_element_name(_path)
the_element = __import__(__base_element_name + name)
if "depend_on" in dir(the_element):
return the_element.depend_on
return []
"""
for elem in tmp_out:
debug.info("find : " + elem)
name = get_element_name(elem)
dependency = get_element_depend(elem)
relative_file = os.path.dirname(os.path.relpath(elem, tools.get_run_path()))
debug.info(" rel_path=" + relative_file)
debug.info(" name=" + name)
debug.info(" depends=" + str(dependency))
"""
out = "# Automatic generation with qworktree ... \n"
out += "TEMPLATE = subdirs\n"
out += "\n"
out += "load(root_directory.prf)\n"
out += "\n"
out += "#import folders\n"
out += "SUBDIRS += \\\n"
for elem in tmp_out:
relative_file = os.path.dirname(os.path.relpath(elem, tools.get_run_path()))
out += " " + relative_file + " \\\n"
out += "\n"
out += "#define dependency\n"
for elem in tmp_out:
dependency = get_element_depend(elem)
name = get_element_name(elem)
out += "#define dependency of " + name + "\n"
for dep in dependency:
out += name + ".depends = " + dep + "\n"
out += "\n"
out += "\n"
out += "\n"
out += "\n"
#debug.info(out)
tools.file_write_data(os.path.join(tools.get_run_path(), os.path.basename(tools.get_run_path())+".pro"), out, only_if_new=True)
out = "# Automatic generation with qworktree ... \n"
out += "\n"
for elem in tmp_out:
name = get_element_name(elem)
relative_file = os.path.dirname(os.path.relpath(elem, tools.get_run_path()))
out += "LIB_DECLARE_DEPENDENCIES_" + name.upper() + " = " + os.path.join(relative_file, "dependencies.pri") + "\n"
out += "\n"
out += "\n"
out += "\n"
#debug.info(out)
tools.file_write_data(os.path.join(tools.get_run_path(), "defines.prf"), out, only_if_new=True)
debug.info("Create basic qmake project")

517
qworktree/arguments.py Normal file
View File

@ -0,0 +1,517 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import sys
from . import debug
##
## @brief Single argument class. It permit to define the getted argument.
##
class ArgElement:
##
## @brief Contructor.
## @param[in] self Class handle
## @param[in] option (string) Option name (write in fullmode ex: '--verbose' even if user write '-v')
## @param[in] value (string) Writed value by the user (defult '')
##
def __init__(self, option, value=""):
self.option = option;
self.arg = value;
##
## @brief Get the name of the argument: (write in fullmode ex: '--verbose' even if user write '-v')
## @param[in] self Class handle
## @return (string) The argument name
##
def get_option_name(self):
return self.option
##
## @brief Get argument data set by the user
## @param[in] self Class handle
## @return (string) The argument value
##
def get_arg(self):
return self.arg
##
## @brief Display the Argument property
## @param[in] self Class handle
##
def display(self):
if len(self.arg) == 0:
debug.info("option : " + self.option)
elif len(self.option) == 0:
debug.info("element : " + self.arg)
else:
debug.info("option : " + self.option + ":" + self.arg)
##
## @brief Declare a possibility of an argument value
##
class ArgDefine:
##
## @brief Contructor.
## @param[in] self Class handle
## @param[in] smallOption (char) Value for the small option ex: '-v' '-k' ... 1 single char element (no need of '-')
## @param[in] bigOption (string) Value of the big option name ex: '--verbose' '--kill' ... stated with -- and with the full name (no need of '--')
## @param[in] list ([[string,string],...]) Optionnal list of availlable option: '--mode=debug' ==> [['debug', 'debug mode'],['release', 'release the software']]
## @param[in] desc (string) user friendly description with this parameter (default "")
## @param[in] haveParam (bool) The option must have a parameter (default False)
##
def __init__(self,
smallOption="", # like v for -v
bigOption="", # like verbose for --verbose
list=[], # ["val", "description"]
desc="",
haveParam=False):
self.option_small = smallOption;
self.option_big = bigOption;
self.list = list;
if len(self.list)!=0:
self.have_param = True
else:
if True==haveParam:
self.have_param = True
else:
self.have_param = False
self.description = desc;
def is_parsable(self):
return True
##
## @brief Get the small name of the option ex: '-v'
## @param[in] self Class handle
## @return (string) Small name value
##
def get_option_small(self):
return self.option_small
##
## @brief Get the big name of the option ex: '--verbose'
## @param[in] self Class handle
## @return (string) Big name value
##
def get_option_big(self):
return self.option_big
##
## @brief Get the status of getting user parameter value
## @param[in] self Class handle
## @return True The user must write a value
## @return False The user must NOT write a value
##
def need_parameters(self):
return self.have_param
##
## @brief Compatibility with @ref ArgSection class
## @param[in] self Class handle
## @return (string) empty string
##
def get_porperties(self):
return ""
##
## @brief Check if the user added value is correct or not with the list of availlable value
## @param[in] self Class handle
## @param[in] argument (string) User parameter value (string)
## @return True The parameter is OK
## @return False The parameter is NOT Availlable
##
def check_availlable(self, argument):
if len(self.list)==0:
return True
for element,desc in self.list:
if element == argument:
return True
return False
##
## @brief Display the argument property when user request help
## @param[in] self Class handle
##
def display(self):
color = debug.get_color_set()
if self.option_small != "" and self.option_big != "":
print(" " + color['red'] + "-" + self.option_small + "" + color['default'] + " / " + color['red'] + "--" + self.option_big + color['default'])
elif self.option_small != "":
print(" " + color['red'] + "-" + self.option_small + color['default'])
elif self.option_big != "":
print(" " + color['red'] + "--" + self.option_big + color['default'])
else:
print(" ???? ==> internal error ...")
if self.description != "":
print(" " + self.description)
if len(self.list)!=0:
hasDescriptiveElement=False
for val,desc in self.list:
if desc!="":
hasDescriptiveElement=True
break;
if hasDescriptiveElement==True:
for val,desc in self.list:
print(" " + val + " : " + desc)
else:
tmpElementPrint = ""
for val,desc in self.list:
if len(tmpElementPrint)!=0:
tmpElementPrint += " / "
tmpElementPrint += val
print(" { " + tmpElementPrint + " }")
##
## @brief Declare an argument value and store it in a parameter
##
class ArgVolatile:
##
## @brief Contructor.
## @param[in] self Class handle
## @param[in] dest_option (string) Where to store the option name
## @param[in] optionnal (bool) this element can be not present
## @param[in] desc (string) user friendly description with this parameter (default "")
##
def __init__(self,
dest_option="",
optionnal=False,
desc=""):
self.dest_option = dest_option;
if dest_option == "":
debug.error("volatil argument must be store in an argument name")
self.optionnal = optionnal;
self.description = desc;
self.count = 0;
def is_parsable(self):
return False
##
## @brief Get the small name of the option ex: '-v'
## @param[in] self Class handle
## @return (string) Small name value
##
def get_option_small(self):
return ""
##
## @brief Get the big name of the option ex: '--verbose'
## @param[in] self Class handle
## @return (string) Big name value
##
def get_option_big(self):
return self.dest_option
##
## @brief Get the status of getting user parameter value
## @param[in] self Class handle
## @return True The user must write a value
## @return False The user must NOT write a value
##
def need_parameters(self):
if self.count == 0:
self.count += 1
return True
return False
##
## @brief Compatibility with @ref ArgSection class
## @param[in] self Class handle
## @return (string) empty string
##
def get_porperties(self):
return " [" + self.dest_option + "]"
##
## @brief Check if the user added value is correct or not with the list of availlable value
## @param[in] self Class handle
## @param[in] argument (string) User parameter value (string)
## @return True The parameter is OK
## @return False The parameter is NOT Availlable
##
def check_availlable(self, argument):
return True
##
## @brief Display the argument property when user request help
## @param[in] self Class handle
##
def display(self):
color = debug.get_color_set()
print(" " + color['red'] + "[" + self.dest_option + "]" + color['default'])
if self.optionnal == True:
print("(OPTIONNAL)")
if self.description != "":
print(" " + self.description)
##
## @brief Section Class definition (permit to add a comment when requesting help
##
class ArgSection:
##
## @brief Constructor
## @param[in] self Class handle
## @param[in] sectionName (string) Name of the cestion ex: "option" is displayed [option]
## @param[in] desc (string) Comment assiciated with the group
##
def __init__(self,
sectionName="",
desc=""):
self.section = sectionName;
self.description = desc;
def is_parsable(self):
return False
##
## @brief Compatibility with @ref ArgDefine class
## @param[in] self Class handle
## @return empty string
##
def get_option_small(self):
return ""
##
## @brief Compatibility with @ref ArgDefine class
## @param[in] self Class handle
## @return empty string
##
def get_option_big(self):
return ""
##
## @brief get property print value with the correct writing mode
## @param[in] self Class handle
## @return String to display in the short line help
##
def get_porperties(self):
color = debug.get_color_set()
return " [" + color['blue'] + self.section + color['default'] + "]"
##
## @brief Display the argument property when user request help
## @param[in] self Class handle
##
def display(self):
color = debug.get_color_set()
print(" [" + color['blue'] + self.section + color['default'] + "] : " + self.description)
##
## @brief Class to define the agmument list availlable for a program
##
class qworktreeArg:
##
## @brief Constructor.
## @param[in] self Class handle
##
def __init__(self):
self.list_properties = []
self._list_element_stop = []
self._last_element_parsed = 0
##
## @brief Add a new argument possibilities...
## @param[in] self Class handle
## @param[in] smallOption (char) Value for the small option ex: '-v' '-k' ... 1 single char element (no need of '-')
## @param[in] bigOption (string) Value of the big option name ex: '--verbose' '--kill' ... stated with -- and with the full name (no need of '--')
## @param[in] list ([[string,string],...]) Optionnal list of availlable option: '--mode=debug' ==> [['debug', 'debug mode'],['release', 'release the software']]
## @param[in] desc (string) user friendly description with this parameter (default "")
## @param[in] haveParam (bool) The option must have a parameter (default False)
##
def add(self, smallOption="", bigOption="", list=[], desc="", haveParam=False):
self.list_properties.append(ArgDefine(smallOption, bigOption, list, desc, haveParam))
def add_arg(self, destOption="", optionnal=False, desc=""):
self.list_properties.append(ArgVolatile(destOption, optionnal, desc))
##
## @brief Add section on argument list
## @param[in] self Class handle
## @param[in] sectionName (string) Name of the cestion ex: "option" is displayed [option]
## @param[in] sectionDesc (string) Comment assiciated with the group
##
def add_section(self, sectionName, sectionDesc):
self.list_properties.append(ArgSection(sectionName, sectionDesc))
##
## @brief Parse the argument set in the command line
## @param[in] self Class handle
## @param[in] start_position_parsing position to start the parsing in the arguments
##
def parse(self, start_position_parsing=1):
list_argument = [] # composed of list element
not_parse_next_element=False
for iii in range(start_position_parsing, len(sys.argv)):
self._last_element_parsed = iii
# special case of parameter in some elements
if not_parse_next_element == True:
not_parse_next_element = False
continue
debug.verbose("parse [" + str(iii) + "]=" + sys.argv[iii])
argument = sys.argv[iii]
# check if we get a stop parsing element:
if argument in self._list_element_stop:
debug.warning("stop at position: " + str(iii))
list_argument.append(ArgElement("", argument))
break;
optionList = argument.split("=")
debug.verbose(str(optionList))
if type(optionList) == type(str()):
option = optionList
else:
option = optionList[0]
optionParam = argument[len(option)+1:]
debug.verbose(option)
argument_found=False;
if option[:2] == "--":
# big argument
for prop in self.list_properties:
if prop.is_parsable()==False:
continue
if prop.get_option_big()=="":
continue
if prop.get_option_big() == option[2:]:
# find it
debug.verbose("find argument 2 : " + option[2:])
if prop.need_parameters()==True:
internalSub = option[2+len(prop.get_option_big()):]
if len(internalSub)!=0:
if len(optionParam)!=0:
# wrong argument ...
debug.warning("maybe wrong argument for : '" + prop.get_option_big() + "' cmdLine='" + argument + "'")
prop.display()
continue
optionParam = internalSub
if len(optionParam)==0:
#Get the next parameters
if len(sys.argv) > iii+1:
optionParam = sys.argv[iii+1]
not_parse_next_element=True
else :
# missing arguments
debug.warning("parsing argument error : '" + prop.get_option_big() + "' Missing : subParameters ... cmdLine='" + argument + "'")
prop.display()
exit(-1)
if prop.check_availlable(optionParam)==False:
debug.warning("argument error : '" + prop.get_option_big() + "' SubParameters not availlable ... cmdLine='" + argument + "' option='" + optionParam + "'")
prop.display()
exit(-1)
list_argument.append(ArgElement(prop.get_option_big(),optionParam))
argument_found = True
else:
if len(optionParam)!=0:
debug.warning("parsing argument error : '" + prop.get_option_big() + "' need no subParameters : '" + optionParam + "' cmdLine='" + argument + "'")
prop.display()
list_argument.append(ArgElement(prop.get_option_big()))
argument_found = True
break;
if argument_found == False:
debug.error("UNKNOW argument : '" + argument + "'")
elif option[:1]=="-":
# small argument
for prop in self.list_properties:
if prop.is_parsable()==False:
continue
if prop.get_option_small()=="":
continue
if prop.get_option_small() == option[1:1+len(prop.get_option_small())]:
# find it
debug.verbose("find argument 1 : " + option[1:1+len(prop.get_option_small())])
if prop.need_parameters()==True:
internalSub = option[1+len(prop.get_option_small()):]
if len(internalSub)!=0:
if len(optionParam)!=0:
# wrong argument ...
debug.warning("maybe wrong argument for : '" + prop.get_option_big() + "' cmdLine='" + argument + "'")
prop.display()
continue
optionParam = internalSub
if len(optionParam)==0:
#Get the next parameters
if len(sys.argv) > iii+1:
optionParam = sys.argv[iii+1]
not_parse_next_element=True
else :
# missing arguments
debug.warning("parsing argument error : '" + prop.get_option_big() + "' Missing : subParameters cmdLine='" + argument + "'")
prop.display()
exit(-1)
if prop.check_availlable(optionParam)==False:
debug.warning("argument error : '" + prop.get_option_big() + "' SubParameters not availlable ... cmdLine='" + argument + "' option='" + optionParam + "'")
prop.display()
exit(-1)
list_argument.append(ArgElement(prop.get_option_big(),optionParam))
argument_found = True
else:
if len(optionParam)!=0:
debug.warning("parsing argument error : '" + prop.get_option_big() + "' need no subParameters : '" + optionParam + "' cmdLine='" + argument + "'")
prop.display()
list_argument.append(ArgElement(prop.get_option_big()))
argument_found = True
break;
if argument_found==False:
# small argument
for prop in self.list_properties:
if prop.is_parsable() == True \
or prop.get_option_big() == "":
continue
if prop.need_parameters() == True:
list_argument.append(ArgElement(prop.get_option_big(), argument))
argument_found = True
break
if argument_found==False:
#unknow element ... ==> just add in the list ...
debug.verbose("unknow argument : " + argument)
list_argument.append(ArgElement("", argument))
for prop in self.list_properties:
if prop.is_parsable() == True \
or prop.get_option_big() == "":
continue
if prop.need_parameters() == True \
and prop.optionnal == False:
debug.error("Missing argument:" + prop.get_option_big())
#for argument in list_argument:
# argument.display()
#exit(0)
return list_argument;
##
## @brief Stop parsing at a specific position
## @param[in] self Class handle
## @param[in] list_of_element List of element that stop the parsing
##
def set_stop_at(self, list_of_element):
self._list_element_stop = list_of_element
##
## @brief get the last element parsed.
## @param[in] self Class handle
##
def get_last_parsed(self):
return self._last_element_parsed
##
## @brief Display help on console output
## @param[in] self Class handle
## @param[in] action_name opation to set at the end of the application name
##
def display(self, action_name=""):
print("usage:")
listOfPropertiesArg = "";
for element in self.list_properties :
listOfPropertiesArg += element.get_porperties()
print(" " + sys.argv[0] + " " + action_name + " " + listOfPropertiesArg + " ...")
for element in self.list_properties :
element.display()

258
qworktree/debug.py Normal file
View File

@ -0,0 +1,258 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import os
import threading
import re
debug_level=3
debug_color=False
color_default= ""
color_red = ""
color_green = ""
color_yellow = ""
color_blue = ""
color_purple = ""
color_cyan = ""
debug_lock = threading.Lock()
##
## @brief Set log level of the console log system
## @param[in] id (int) Value of the log level:
## 0: None
## 1: error
## 2: warning
## 3: info
## 4: debug
## 5: verbose
## 6: extreme_verbose
##
def set_level(id):
global debug_level
debug_level = id
#print "SetDebug level at " + str(debug_level)
##
## @brief Get the current debug leval
## @return The value of the log level. Show: @ref set_level
##
def get_level():
global debug_level
return debug_level
##
## @brief Enable color of the console Log system
##
def enable_color():
global debug_color
debug_color = True
global color_default
color_default= "\033[00m"
global color_red
color_red = "\033[31m"
global color_green
color_green = "\033[32m"
global color_yellow
color_yellow = "\033[33m"
global color_blue
color_blue = "\033[01;34m"
global color_purple
color_purple = "\033[35m"
global color_cyan
color_cyan = "\033[36m"
##
## @brief Disable color of the console Log system
##
def disable_color():
global debug_color
debug_color = True
global color_default
color_default= ""
global color_red
color_red = ""
global color_green
color_green = ""
global color_yellow
color_yellow = ""
global color_blue
color_blue = ""
global color_purple
color_purple = ""
global color_cyan
color_cyan = ""
##
## @brief Print a extreme verbose log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def extreme_verbose(input, force=False):
global debug_lock
global debug_level
if debug_level >= 6 \
or force == True:
debug_lock.acquire()
print(color_blue + input + color_default)
debug_lock.release()
##
## @brief Print a verbose log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def verbose(input, force=False):
global debug_lock
global debug_level
if debug_level >= 5 \
or force == True:
debug_lock.acquire()
print(color_blue + input + color_default)
debug_lock.release()
##
## @brief Print a debug log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def debug(input, force=False):
global debug_lock
global debug_level
if debug_level >= 4 \
or force == True:
debug_lock.acquire()
print(color_green + input + color_default)
debug_lock.release()
##
## @brief Print an info log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def info(input, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(input + color_default)
debug_lock.release()
##
## @brief Print a warning log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def warning(input, force=False):
global debug_lock
global debug_level
if debug_level >= 2 \
or force == True:
debug_lock.acquire()
print(color_purple + "[WARNING] " + input + color_default)
debug_lock.release()
##
## @brief Print a todo log
## @param[in] input (string) Value to print if level is enough
## @param[in] force (bool) force display (no check of log level)
##
def todo(input, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(color_purple + "[TODO] " + input + color_default)
debug_lock.release()
##
## @brief Print an error log
## @param[in] input (string) Value to print if level is enough
## @param[in] thread_id (int) Current thead ID of the builder thread
## @param[in] force (bool) force display (no check of log level)
## @param[in] crash (bool) build error has appear ==> request stop of all builds
##
def error(input, thread_id=-1, force=False, crash=True):
global debug_lock
global debug_level
if debug_level >= 1 \
or force == True:
debug_lock.acquire()
print(color_red + "[ERROR] " + input + color_default)
debug_lock.release()
if crash == True:
exit(-1)
#os_exit(-1)
#raise "error happend"
##
## @brief Print a log for a specific element action like generateing .so or binary ...
## @param[in] type (string) type of action. Like: "copy file", "StaticLib", "Prebuild", "Library" ...
## @param[in] lib (string) Name of the library/binary/package that action is done
## @param[in] dir (string) build direction. ex: "<==", "==>" ...
## @param[in] name (string) Destination of the data
## @param[in] force (bool) force display (no check of log level)
##
def print_element(type, lib, dir, name, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(color_cyan + type + color_default + " : " + color_yellow + lib + color_default + " " + dir + " " + color_blue + name + color_default)
debug_lock.release()
##
## @brief Print a compilation return (output)
## @param[in] my_string (string) Std-error/std-info that is generate by the build system
##
def print_compilator(my_string):
global debug_color
global debug_lock
if debug_color == True:
my_string = my_string.replace('\\n', '\n')
my_string = my_string.replace('\\t', '\t')
my_string = my_string.replace('error:', color_red+'error:'+color_default)
my_string = my_string.replace('warning:', color_purple+'warning:'+color_default)
my_string = my_string.replace('note:', color_green+'note:'+color_default)
my_string = re.sub(r'([/\w_-]+\.\w+):', r'-COLORIN-\1-COLOROUT-:', my_string)
my_string = my_string.replace('-COLORIN-', color_yellow)
my_string = my_string.replace('-COLOROUT-', color_default)
debug_lock.acquire()
print(my_string)
debug_lock.release()
##
## @brief Get the list of default color
## @return A map with keys: "default","red","green","yellow","blue","purple","cyan"
##
def get_color_set() :
global color_default
global color_red
global color_green
global color_yellow
global color_blue
global color_purple
global color_cyan
return {
"default": color_default,
"red": color_red,
"green": color_green,
"yellow": color_yellow,
"blue": color_blue,
"purple": color_purple,
"cyan": color_cyan,
}

26
qworktree/env.py Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
# Local import
from . import debug
import os
system_base_name = "qworktree"
def set_system_base_name(val):
global system_base_name
system_base_name = val
debug.debug("Set basename: '" + str(system_base_name) + "'")
def get_system_base_name():
global system_base_name
return system_base_name

277
qworktree/tools.py Normal file
View File

@ -0,0 +1,277 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import os
import shutil
import errno
import fnmatch
import stat
# Local import
from . import debug
from . import env
"""
"""
def get_run_path():
return os.getcwd()
"""
"""
def get_current_path(file):
return os.path.dirname(os.path.realpath(file))
def create_directory(path):
try:
os.stat(path)
except:
os.makedirs(path)
def create_directory_of_file(file):
path = os.path.dirname(file)
create_directory(path)
def get_list_sub_path(path):
# TODO : os.listdir(path)
for dirname, dirnames, filenames in os.walk(path):
return dirnames
return []
def remove_path_and_sub_path(path):
if os.path.isdir(path):
debug.verbose("remove path : '" + path + "'")
shutil.rmtree(path)
def remove_file(path):
if os.path.isfile(path):
os.remove(path)
elif os.path.islink(path):
os.remove(path)
def file_size(path):
if not os.path.isfile(path):
return 0
statinfo = os.stat(path)
return statinfo.st_size
def file_read_data(path, binary=False):
if not os.path.isfile(path):
return ""
if binary == True:
file = open(path, "rb")
else:
file = open(path, "r")
data_file = file.read()
file.close()
return data_file
def version_to_string(version):
version_ID = ""
for id in version:
if len(version_ID) != 0:
if type(id) == str:
version_ID += "-"
else:
version_ID += "."
version_ID += str(id)
return version_ID
##
## @brief Write data in a specific path.
## @param[in] path Path of the data might be written.
## @param[in] data Data To write in the file.
## @param[in] only_if_new (default: False) Write data only if data is different.
## @return True Something has been copied
## @return False Nothing has been copied
##
def file_write_data(path, data, only_if_new=False):
if only_if_new == True:
old_data = file_read_data(path)
if old_data == data:
return False
#real write of data:
create_directory_of_file(path)
file = open(path, "w")
file.write(data)
file.close()
return True
def list_to_str(list):
if type(list) == type(str()):
return list + " "
else:
result = ""
# mulyiple imput in the list ...
for elem in list:
result += list_to_str(elem)
return result
def add_prefix(prefix,list):
if type(list) == type(None):
return ""
if type(list) == type(str()):
return prefix+list
else:
if len(list)==0:
return ''
else:
result=[]
for elem in list:
result.append(prefix+elem)
return result
def store_command(cmd_line, file):
# write cmd line only after to prevent errors ...
if file == "" \
or file == None:
return;
debug.verbose("create cmd file: " + file)
# Create directory:
create_directory_of_file(file)
# Store the command Line:
file2 = open(file, "w")
file2.write(cmd_line)
file2.flush()
file2.close()
def get_type_string(in_type):
if type(in_type) == str:
return "string"
elif type(in_type) == list:
return "list"
elif type(in_type) == dict:
return "dict"
return "unknow"
## List tools:
def list_append_and_check(listout, newElement, order):
for element in listout:
if element==newElement:
return
listout.append(newElement)
if order == True:
if type(newElement) is not dict:
listout.sort()
def list_append_to(out_list, in_list, order=False):
if type(in_list) == str:
list_append_and_check(out_list, in_list, order)
elif type(in_list) == list:
# mulyiple imput in the list ...
for elem in in_list:
list_append_and_check(out_list, elem, order)
elif type(in_list) == dict:
list_append_and_check(out_list, in_list, order)
else:
debug.warning("can not add in list other than {list/dict/str} : " + str(type(in_list)))
def list_append_to_2(listout, module, in_list, order=False):
# sepcial cse of bool
if type(in_list) == bool:
listout[module] = in_list
return
# add list in the Map
if module not in listout:
listout[module] = []
# add elements...
list_append_to(listout[module], in_list, order)
##
## @brief The vertion number can be set in an external file to permit to have a singe position to change when create a vew version
## @param[in] path_module (string) Path of the module position
## @param[in] filename_or_version (string or list) Path of the version or the real version lint parameter
## @return (list) List of version number
##
def get_version_from_file_or_direct(path_module, filename_or_version):
# check case of iser set the version directly
if type(filename_or_version) == list:
return filename_or_version
# this use a version file
file_data = file_read_data(os.path.join(path_module, filename_or_version))
if len(file_data) == 0:
debug.warning("not enought data in the file version size=0 " + path_module + " / " + filename_or_version)
return [0,0,0]
lines = file_data.split("\n")
if len(lines) != 1:
debug.warning("More thatn one line in the file version ==> bas case use mode: 'XX', XX.YYY', 'XX.Y.ZZZ' or 'XX.Y-dev' : " + path_module + " / " + filename_or_version)
return [0,0,0]
line = lines[0]
debug.debug("Parse line: '" + line + "'")
#check if we have "-dev"
dev_mode = ""
list_tiret = line.split('-')
if len(list_tiret) > 2:
debug.warning("more than one '-' in version file " + str(filename_or_version) + " : '" + str(list_tiret) + "' in '" + path_module + "'")
if len(list_tiret) >= 2:
dev_mode = list_tiret[1]
line = list_tiret[0]
out = []
list_elem = line.split('.')
for elem in list_elem:
out.append(int(elem))
if dev_mode != "":
out.append(dev_mode)
debug.debug(" ==> " + str(out))
return out
##
## @brief Get the list of the authors frim an input list or a file
## @param[in] path_module (string) Path of the module position
## @param[in] filename_or_version (string or list) Path of the author file or the real list of authors
## @return (list) List of authors
##
def get_maintainer_from_file_or_direct(path_module, filename_or_author):
# check case of iser set the version directly
if type(filename_or_author) == list:
return filename_or_author
# this use a version file
file_data = file_read_data(os.path.join(path_module, filename_or_author))
if len(file_data) == 0:
debug.warning("not enought data in the file author size=0 " + path_module + " / " + filename_or_author)
return []
# One user by line and # for comment line
out = []
for elem in file_data.split('\n'):
if len(elem) == 0:
continue
if elem[0] == "#":
# comment ...
continue
out.append(elem)
return out
def remove_element(data, to_remove):
base_data = []
for elem in data:
if type(elem) == list:
for elem2 in elem:
base_data.append(elem2)
else:
base_data.append(elem)
base_remove = []
for elem in to_remove:
if type(elem) == list:
for elem2 in elem:
base_remove.append(elem2)
else:
base_remove.append(elem)
out = []
for elem in base_data:
if elem not in base_remove:
out.append(elem)
return out;

0
setup.cfg Normal file
View File

48
setup.py Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2019, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
from setuptools import setup
def readme():
with open('README.rst') as f:
return f.read()
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
setup(name='qworktree',
version='0.1.0',
description='qworktree generator of main Qt .pro file for a full worktree',
long_description=readme(),
url='http://github.com/HeeroYui/qworktree',
author='Edouard DUPIN',
author_email='yui.heero@gmail.com',
license='MPL-2',
packages=['qworktree'],
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
'Programming Language :: Python',
'Topic :: Software Development :: Build Tools'
],
keywords='qmake worktree build qt',
scripts=['bin/qworktree'],
# Does not work on MacOs
#data_file=[
# ('/etc/bash_completion.d', ['bash-autocompletion/lutin']),
#],
install_requires=[
'lxml',
],
include_package_data = True,
zip_safe=False)
#To developp: sudo ./setup.py install
# sudo ./setup.py develop
#TO register all in pip: ./setup.py register sdist upload