diff options
| -rw-r--r-- | bitbake/lib/bb/utils.py | 601 |
1 files changed, 453 insertions, 148 deletions
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index a1e093925b..a2806fd360 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
| @@ -82,7 +82,16 @@ def explode_version(s): | |||
| 82 | return r | 82 | return r |
| 83 | 83 | ||
| 84 | def split_version(s): | 84 | def split_version(s): |
| 85 | """Split a version string into its constituent parts (PE, PV, PR)""" | 85 | """Split a version string into its constituent parts (PE, PV, PR). |
| 86 | |||
| 87 | Arguments: | ||
| 88 | |||
| 89 | - ``s``: version string. The format of the input string should be:: | ||
| 90 | |||
| 91 | ${PE}:${PV}-${PR} | ||
| 92 | |||
| 93 | Returns a tuple ``(pe, pv, pr)``. | ||
| 94 | """ | ||
| 86 | s = s.strip(" <>=") | 95 | s = s.strip(" <>=") |
| 87 | e = 0 | 96 | e = 0 |
| 88 | if s.count(':'): | 97 | if s.count(':'): |
| @@ -134,16 +143,30 @@ def vercmp(ta, tb): | |||
| 134 | return r | 143 | return r |
| 135 | 144 | ||
| 136 | def vercmp_string(a, b): | 145 | def vercmp_string(a, b): |
| 137 | """ Split version strings and compare them """ | 146 | """ Split version strings using ``bb.utils.split_version()`` and compare |
| 147 | them with ``bb.utils.vercmp().`` | ||
| 148 | |||
| 149 | Arguments: | ||
| 150 | |||
| 151 | - ``a``: left version string operand. | ||
| 152 | - ``b``: right version string operand. | ||
| 153 | |||
| 154 | Returns what ``bb.utils.vercmp()`` returns.""" | ||
| 138 | ta = split_version(a) | 155 | ta = split_version(a) |
| 139 | tb = split_version(b) | 156 | tb = split_version(b) |
| 140 | return vercmp(ta, tb) | 157 | return vercmp(ta, tb) |
| 141 | 158 | ||
| 142 | def vercmp_string_op(a, b, op): | 159 | def vercmp_string_op(a, b, op): |
| 143 | """ | 160 | """ |
| 144 | Compare two versions and check if the specified comparison operator matches the result of the comparison. | 161 | Takes the return value ``bb.utils.vercmp()`` and returns the operation |
| 145 | This function is fairly liberal about what operators it will accept since there are a variety of styles | 162 | defined by ``op`` between the return value and 0. |
| 146 | depending on the context. | 163 | |
| 164 | Arguments: | ||
| 165 | |||
| 166 | - ``a``: left version string operand. | ||
| 167 | - ``b``: right version string operand. | ||
| 168 | - ``op``: operator string. Can be one of ``=``, ``==``, ``<=``, ``>=``, | ||
| 169 | ``>``, ``>>``, ``<``, ``<<`` or ``!=``. | ||
| 147 | """ | 170 | """ |
| 148 | res = vercmp_string(a, b) | 171 | res = vercmp_string(a, b) |
| 149 | if op in ('=', '=='): | 172 | if op in ('=', '=='): |
| @@ -163,9 +186,16 @@ def vercmp_string_op(a, b, op): | |||
| 163 | 186 | ||
| 164 | def explode_deps(s): | 187 | def explode_deps(s): |
| 165 | """ | 188 | """ |
| 166 | Take an RDEPENDS style string of format: | 189 | Takes an RDEPENDS style string of format:: |
| 167 | "DEPEND1 (optional version) DEPEND2 (optional version) ..." | 190 | |
| 168 | and return a list of dependencies. | 191 | DEPEND1 (optional version) DEPEND2 (optional version) ... |
| 192 | |||
| 193 | Arguments: | ||
| 194 | |||
| 195 | - ``s``: input RDEPENDS style string | ||
| 196 | |||
| 197 | Returns a list of dependencies. | ||
| 198 | |||
| 169 | Version information is ignored. | 199 | Version information is ignored. |
| 170 | """ | 200 | """ |
| 171 | r = [] | 201 | r = [] |
| @@ -187,9 +217,17 @@ def explode_deps(s): | |||
| 187 | 217 | ||
| 188 | def explode_dep_versions2(s, *, sort=True): | 218 | def explode_dep_versions2(s, *, sort=True): |
| 189 | """ | 219 | """ |
| 190 | Take an RDEPENDS style string of format: | 220 | Takes an RDEPENDS style string of format:: |
| 191 | "DEPEND1 (optional version) DEPEND2 (optional version) ..." | 221 | |
| 192 | and return a dictionary of dependencies and versions. | 222 | DEPEND1 (optional version) DEPEND2 (optional version) ... |
| 223 | |||
| 224 | Arguments: | ||
| 225 | |||
| 226 | - ``s``: input RDEPENDS style string | ||
| 227 | - ``*``: *Unused*. | ||
| 228 | - ``sort``: whether to sort the output or not. | ||
| 229 | |||
| 230 | Returns a dictionary of dependencies and versions. | ||
| 193 | """ | 231 | """ |
| 194 | r = collections.OrderedDict() | 232 | r = collections.OrderedDict() |
| 195 | l = s.replace(",", "").split() | 233 | l = s.replace(",", "").split() |
| @@ -254,10 +292,17 @@ def explode_dep_versions2(s, *, sort=True): | |||
| 254 | 292 | ||
| 255 | def explode_dep_versions(s): | 293 | def explode_dep_versions(s): |
| 256 | """ | 294 | """ |
| 257 | Take an RDEPENDS style string of format: | 295 | Take an RDEPENDS style string of format:: |
| 258 | "DEPEND1 (optional version) DEPEND2 (optional version) ..." | 296 | |
| 259 | skip null value and items appeared in dependency string multiple times | 297 | DEPEND1 (optional version) DEPEND2 (optional version) ... |
| 260 | and return a dictionary of dependencies and versions. | 298 | |
| 299 | Skips null values and items appeared in dependency string multiple times. | ||
| 300 | |||
| 301 | Arguments: | ||
| 302 | |||
| 303 | - ``s``: input RDEPENDS style string | ||
| 304 | |||
| 305 | Returns a dictionary of dependencies and versions. | ||
| 261 | """ | 306 | """ |
| 262 | r = explode_dep_versions2(s) | 307 | r = explode_dep_versions2(s) |
| 263 | for d in r: | 308 | for d in r: |
| @@ -271,7 +316,17 @@ def explode_dep_versions(s): | |||
| 271 | 316 | ||
| 272 | def join_deps(deps, commasep=True): | 317 | def join_deps(deps, commasep=True): |
| 273 | """ | 318 | """ |
| 274 | Take the result from explode_dep_versions and generate a dependency string | 319 | Take a result from ``bb.utils.explode_dep_versions()`` and generate a |
| 320 | dependency string. | ||
| 321 | |||
| 322 | Arguments: | ||
| 323 | |||
| 324 | - ``deps``: dictionary of dependencies and versions. | ||
| 325 | - ``commasep``: makes the return value separated by commas if ``True``, | ||
| 326 | separated by spaces otherwise. | ||
| 327 | |||
| 328 | Returns a comma-separated (space-separated if ``comma-sep`` is ``False``) | ||
| 329 | string of dependencies and versions. | ||
| 275 | """ | 330 | """ |
| 276 | result = [] | 331 | result = [] |
| 277 | for dep in deps: | 332 | for dep in deps: |
| @@ -433,7 +488,11 @@ def better_eval(source, locals, extraglobals = None): | |||
| 433 | 488 | ||
| 434 | @contextmanager | 489 | @contextmanager |
| 435 | def fileslocked(files, *args, **kwargs): | 490 | def fileslocked(files, *args, **kwargs): |
| 436 | """Context manager for locking and unlocking file locks.""" | 491 | """Context manager for locking and unlocking file locks. Uses |
| 492 | ``bb.utils.lockfile()`` and ``bb.utils.unlockfile()`` to lock and unlock | ||
| 493 | files. | ||
| 494 | |||
| 495 | No return value.""" | ||
| 437 | locks = [] | 496 | locks = [] |
| 438 | if files: | 497 | if files: |
| 439 | for lockfile in files: | 498 | for lockfile in files: |
| @@ -450,14 +509,23 @@ def fileslocked(files, *args, **kwargs): | |||
| 450 | 509 | ||
| 451 | def lockfile(name, shared=False, retry=True, block=False): | 510 | def lockfile(name, shared=False, retry=True, block=False): |
| 452 | """ | 511 | """ |
| 453 | Use the specified file as a lock file, return when the lock has | 512 | Use the specified file (with filename ``name``) as a lock file, return when |
| 454 | been acquired. Returns a variable to pass to unlockfile(). | 513 | the lock has been acquired. Returns a variable to pass to unlockfile(). |
| 455 | Parameters: | 514 | |
| 456 | retry: True to re-try locking if it fails, False otherwise | 515 | Arguments: |
| 457 | block: True to block until the lock succeeds, False otherwise | 516 | |
| 517 | - ``shared``: sets the lock as a shared lock instead of an | ||
| 518 | exclusive lock. | ||
| 519 | - ``retry``: ``True`` to re-try locking if it fails, ``False`` | ||
| 520 | otherwise. | ||
| 521 | - ``block``: ``True`` to block until the lock succeeds, | ||
| 522 | ``False`` otherwise. | ||
| 523 | |||
| 458 | The retry and block parameters are kind of equivalent unless you | 524 | The retry and block parameters are kind of equivalent unless you |
| 459 | consider the possibility of sending a signal to the process to break | 525 | consider the possibility of sending a signal to the process to break |
| 460 | out - at which point you want block=True rather than retry=True. | 526 | out - at which point you want block=True rather than retry=True. |
| 527 | |||
| 528 | Returns the locked file descriptor in case of success, ``None`` otherwise. | ||
| 461 | """ | 529 | """ |
| 462 | basename = os.path.basename(name) | 530 | basename = os.path.basename(name) |
| 463 | if len(basename) > 255: | 531 | if len(basename) > 255: |
| @@ -516,7 +584,13 @@ def lockfile(name, shared=False, retry=True, block=False): | |||
| 516 | 584 | ||
| 517 | def unlockfile(lf): | 585 | def unlockfile(lf): |
| 518 | """ | 586 | """ |
| 519 | Unlock a file locked using lockfile() | 587 | Unlock a file locked using ``bb.utils.lockfile()``. |
| 588 | |||
| 589 | Arguments: | ||
| 590 | |||
| 591 | - ``lf``: the locked file descriptor. | ||
| 592 | |||
| 593 | No return value. | ||
| 520 | """ | 594 | """ |
| 521 | try: | 595 | try: |
| 522 | # If we had a shared lock, we need to promote to exclusive before | 596 | # If we had a shared lock, we need to promote to exclusive before |
| @@ -544,7 +618,11 @@ def _hasher(method, filename): | |||
| 544 | 618 | ||
| 545 | def md5_file(filename): | 619 | def md5_file(filename): |
| 546 | """ | 620 | """ |
| 547 | Return the hex string representation of the MD5 checksum of filename. | 621 | Arguments: |
| 622 | |||
| 623 | - ``filename``: path to the input file. | ||
| 624 | |||
| 625 | Returns the hexadecimal string representation of the MD5 checksum of filename. | ||
| 548 | """ | 626 | """ |
| 549 | import hashlib | 627 | import hashlib |
| 550 | try: | 628 | try: |
| @@ -556,39 +634,59 @@ def md5_file(filename): | |||
| 556 | 634 | ||
| 557 | def sha256_file(filename): | 635 | def sha256_file(filename): |
| 558 | """ | 636 | """ |
| 559 | Return the hex string representation of the 256-bit SHA checksum of | 637 | Returns the hexadecimal representation of the 256-bit SHA checksum of |
| 560 | filename. | 638 | filename. |
| 639 | |||
| 640 | Arguments: | ||
| 641 | |||
| 642 | - ``filename``: path to the file. | ||
| 561 | """ | 643 | """ |
| 562 | import hashlib | 644 | import hashlib |
| 563 | return _hasher(hashlib.sha256(), filename) | 645 | return _hasher(hashlib.sha256(), filename) |
| 564 | 646 | ||
| 565 | def sha1_file(filename): | 647 | def sha1_file(filename): |
| 566 | """ | 648 | """ |
| 567 | Return the hex string representation of the SHA1 checksum of the filename | 649 | Returns the hexadecimal representation of the SHA1 checksum of the filename |
| 650 | |||
| 651 | Arguments: | ||
| 652 | |||
| 653 | - ``filename``: path to the file. | ||
| 568 | """ | 654 | """ |
| 569 | import hashlib | 655 | import hashlib |
| 570 | return _hasher(hashlib.sha1(), filename) | 656 | return _hasher(hashlib.sha1(), filename) |
| 571 | 657 | ||
| 572 | def sha384_file(filename): | 658 | def sha384_file(filename): |
| 573 | """ | 659 | """ |
| 574 | Return the hex string representation of the SHA384 checksum of the filename | 660 | Returns the hexadecimal representation of the SHA384 checksum of the filename |
| 661 | |||
| 662 | Arguments: | ||
| 663 | |||
| 664 | - ``filename``: path to the file. | ||
| 575 | """ | 665 | """ |
| 576 | import hashlib | 666 | import hashlib |
| 577 | return _hasher(hashlib.sha384(), filename) | 667 | return _hasher(hashlib.sha384(), filename) |
| 578 | 668 | ||
| 579 | def sha512_file(filename): | 669 | def sha512_file(filename): |
| 580 | """ | 670 | """ |
| 581 | Return the hex string representation of the SHA512 checksum of the filename | 671 | Returns the hexadecimal representation of the SHA512 checksum of the filename |
| 672 | |||
| 673 | Arguments: | ||
| 674 | |||
| 675 | - ``filename``: path to the file. | ||
| 582 | """ | 676 | """ |
| 583 | import hashlib | 677 | import hashlib |
| 584 | return _hasher(hashlib.sha512(), filename) | 678 | return _hasher(hashlib.sha512(), filename) |
| 585 | 679 | ||
| 586 | def goh1_file(filename): | 680 | def goh1_file(filename): |
| 587 | """ | 681 | """ |
| 588 | Return the hex string representation of the Go mod h1 checksum of the | 682 | Returns the hexadecimal string representation of the Go mod h1 checksum of the |
| 589 | filename. The Go mod h1 checksum uses the Go dirhash package. The package | 683 | filename. The Go mod h1 checksum uses the Go dirhash package. The package |
| 590 | defines hashes over directory trees and is used by go mod for mod files and | 684 | defines hashes over directory trees and is used by go mod for mod files and |
| 591 | zip archives. | 685 | zip archives. |
| 686 | |||
| 687 | Arguments: | ||
| 688 | |||
| 689 | - ``filename``: path to the file. | ||
| 592 | """ | 690 | """ |
| 593 | import hashlib | 691 | import hashlib |
| 594 | import zipfile | 692 | import zipfile |
| @@ -609,8 +707,8 @@ def goh1_file(filename): | |||
| 609 | return method.hexdigest() | 707 | return method.hexdigest() |
| 610 | 708 | ||
| 611 | def preserved_envvars_exported(): | 709 | def preserved_envvars_exported(): |
| 612 | """Variables which are taken from the environment and placed in and exported | 710 | """Returns the list of variables which are taken from the environment and |
| 613 | from the metadata""" | 711 | placed in and exported from the metadata.""" |
| 614 | return [ | 712 | return [ |
| 615 | 'BB_TASKHASH', | 713 | 'BB_TASKHASH', |
| 616 | 'HOME', | 714 | 'HOME', |
| @@ -624,7 +722,8 @@ def preserved_envvars_exported(): | |||
| 624 | ] | 722 | ] |
| 625 | 723 | ||
| 626 | def preserved_envvars(): | 724 | def preserved_envvars(): |
| 627 | """Variables which are taken from the environment and placed in the metadata""" | 725 | """Returns the list of variables which are taken from the environment and |
| 726 | placed in the metadata.""" | ||
| 628 | v = [ | 727 | v = [ |
| 629 | 'BBPATH', | 728 | 'BBPATH', |
| 630 | 'BB_PRESERVE_ENV', | 729 | 'BB_PRESERVE_ENV', |
| @@ -633,7 +732,9 @@ def preserved_envvars(): | |||
| 633 | return v + preserved_envvars_exported() | 732 | return v + preserved_envvars_exported() |
| 634 | 733 | ||
| 635 | def check_system_locale(): | 734 | def check_system_locale(): |
| 636 | """Make sure the required system locale are available and configured""" | 735 | """Make sure the required system locale are available and configured. |
| 736 | |||
| 737 | No return value.""" | ||
| 637 | default_locale = locale.getlocale(locale.LC_CTYPE) | 738 | default_locale = locale.getlocale(locale.LC_CTYPE) |
| 638 | 739 | ||
| 639 | try: | 740 | try: |
| @@ -651,6 +752,12 @@ def filter_environment(good_vars): | |||
| 651 | """ | 752 | """ |
| 652 | Create a pristine environment for bitbake. This will remove variables that | 753 | Create a pristine environment for bitbake. This will remove variables that |
| 653 | are not known and may influence the build in a negative way. | 754 | are not known and may influence the build in a negative way. |
| 755 | |||
| 756 | Arguments: | ||
| 757 | |||
| 758 | - ``good_vars``: list of variable to exclude from the filtering. | ||
| 759 | |||
| 760 | No return value. | ||
| 654 | """ | 761 | """ |
| 655 | 762 | ||
| 656 | removed_vars = {} | 763 | removed_vars = {} |
| @@ -695,6 +802,8 @@ def clean_environment(): | |||
| 695 | """ | 802 | """ |
| 696 | Clean up any spurious environment variables. This will remove any | 803 | Clean up any spurious environment variables. This will remove any |
| 697 | variables the user hasn't chosen to preserve. | 804 | variables the user hasn't chosen to preserve. |
| 805 | |||
| 806 | No return value. | ||
| 698 | """ | 807 | """ |
| 699 | if 'BB_PRESERVE_ENV' not in os.environ: | 808 | if 'BB_PRESERVE_ENV' not in os.environ: |
| 700 | good_vars = approved_variables() | 809 | good_vars = approved_variables() |
| @@ -705,6 +814,8 @@ def clean_environment(): | |||
| 705 | def empty_environment(): | 814 | def empty_environment(): |
| 706 | """ | 815 | """ |
| 707 | Remove all variables from the environment. | 816 | Remove all variables from the environment. |
| 817 | |||
| 818 | No return value. | ||
| 708 | """ | 819 | """ |
| 709 | for s in list(os.environ.keys()): | 820 | for s in list(os.environ.keys()): |
| 710 | os.unsetenv(s) | 821 | os.unsetenv(s) |
| @@ -713,6 +824,12 @@ def empty_environment(): | |||
| 713 | def build_environment(d): | 824 | def build_environment(d): |
| 714 | """ | 825 | """ |
| 715 | Build an environment from all exported variables. | 826 | Build an environment from all exported variables. |
| 827 | |||
| 828 | Arguments: | ||
| 829 | |||
| 830 | - ``d``: the data store. | ||
| 831 | |||
| 832 | No return value. | ||
| 716 | """ | 833 | """ |
| 717 | import bb.data | 834 | import bb.data |
| 718 | for var in bb.data.keys(d): | 835 | for var in bb.data.keys(d): |
| @@ -737,7 +854,17 @@ def _check_unsafe_delete_path(path): | |||
| 737 | return False | 854 | return False |
| 738 | 855 | ||
| 739 | def remove(path, recurse=False, ionice=False): | 856 | def remove(path, recurse=False, ionice=False): |
| 740 | """Equivalent to rm -f or rm -rf""" | 857 | """Equivalent to rm -f or rm -rf. |
| 858 | |||
| 859 | Arguments: | ||
| 860 | |||
| 861 | - ``path``: path to file/directory to remove. | ||
| 862 | - ``recurse``: deletes recursively if ``True``. | ||
| 863 | - ``ionice``: prepends ``ionice -c 3`` to the ``rm`` command. See ``man | ||
| 864 | ionice``. | ||
| 865 | |||
| 866 | No return value. | ||
| 867 | """ | ||
| 741 | if not path: | 868 | if not path: |
| 742 | return | 869 | return |
| 743 | if recurse: | 870 | if recurse: |
| @@ -758,7 +885,17 @@ def remove(path, recurse=False, ionice=False): | |||
| 758 | raise | 885 | raise |
| 759 | 886 | ||
| 760 | def prunedir(topdir, ionice=False): | 887 | def prunedir(topdir, ionice=False): |
| 761 | """ Delete everything reachable from the directory named in 'topdir'. """ | 888 | """ |
| 889 | Delete everything reachable from the directory named in ``topdir``. | ||
| 890 | |||
| 891 | Arguments: | ||
| 892 | |||
| 893 | - ``topdir``: directory path. | ||
| 894 | - ``ionice``: prepends ``ionice -c 3`` to the ``rm`` command. See ``man | ||
| 895 | ionice``. | ||
| 896 | |||
| 897 | No return value. | ||
| 898 | """ | ||
| 762 | # CAUTION: This is dangerous! | 899 | # CAUTION: This is dangerous! |
| 763 | if _check_unsafe_delete_path(topdir): | 900 | if _check_unsafe_delete_path(topdir): |
| 764 | raise Exception('bb.utils.prunedir: called with dangerous path "%s", refusing to delete!' % topdir) | 901 | raise Exception('bb.utils.prunedir: called with dangerous path "%s", refusing to delete!' % topdir) |
| @@ -770,8 +907,15 @@ def prunedir(topdir, ionice=False): | |||
| 770 | # | 907 | # |
| 771 | def prune_suffix(var, suffixes, d): | 908 | def prune_suffix(var, suffixes, d): |
| 772 | """ | 909 | """ |
| 773 | See if var ends with any of the suffixes listed and | 910 | Check if ``var`` ends with any of the suffixes listed in ``suffixes`` and |
| 774 | remove it if found | 911 | remove it if found. |
| 912 | |||
| 913 | Arguments: | ||
| 914 | |||
| 915 | - ``var``: string to check for suffixes. | ||
| 916 | - ``suffixes``: list of strings representing suffixes to check for. | ||
| 917 | |||
| 918 | Returns the string ``var`` without the suffix. | ||
| 775 | """ | 919 | """ |
| 776 | for suffix in suffixes: | 920 | for suffix in suffixes: |
| 777 | if suffix and var.endswith(suffix): | 921 | if suffix and var.endswith(suffix): |
| @@ -780,7 +924,13 @@ def prune_suffix(var, suffixes, d): | |||
| 780 | 924 | ||
| 781 | def mkdirhier(directory): | 925 | def mkdirhier(directory): |
| 782 | """Create a directory like 'mkdir -p', but does not complain if | 926 | """Create a directory like 'mkdir -p', but does not complain if |
| 783 | directory already exists like os.makedirs | 927 | directory already exists like ``os.makedirs()``. |
| 928 | |||
| 929 | Arguments: | ||
| 930 | |||
| 931 | - ``directory``: path to the directory. | ||
| 932 | |||
| 933 | No return value. | ||
| 784 | """ | 934 | """ |
| 785 | if '${' in str(directory): | 935 | if '${' in str(directory): |
| 786 | bb.fatal("Directory name {} contains unexpanded bitbake variable. This may cause build failures and WORKDIR polution.".format(directory)) | 936 | bb.fatal("Directory name {} contains unexpanded bitbake variable. This may cause build failures and WORKDIR polution.".format(directory)) |
| @@ -791,10 +941,24 @@ def mkdirhier(directory): | |||
| 791 | raise e | 941 | raise e |
| 792 | 942 | ||
| 793 | def movefile(src, dest, newmtime = None, sstat = None): | 943 | def movefile(src, dest, newmtime = None, sstat = None): |
| 794 | """Moves a file from src to dest, preserving all permissions and | 944 | """Moves a file from ``src`` to ``dest``, preserving all permissions and |
| 795 | attributes; mtime will be preserved even when moving across | 945 | attributes; mtime will be preserved even when moving across |
| 796 | filesystems. Returns true on success and false on failure. Move is | 946 | filesystems. Returns ``True`` on success and ``False`` on failure. Move is |
| 797 | atomic. | 947 | atomic. |
| 948 | |||
| 949 | Arguments: | ||
| 950 | |||
| 951 | - ``src`` -- Source file. | ||
| 952 | - ``dest`` -- Destination file. | ||
| 953 | - ``newmtime`` -- new mtime to be passed as float seconds since the epoch. | ||
| 954 | - ``sstat`` -- os.stat_result to use for the destination file. | ||
| 955 | |||
| 956 | Returns an ``os.stat_result`` of the destination file if the | ||
| 957 | source file is a symbolic link or the ``sstat`` argument represents a | ||
| 958 | symbolic link - in which case the destination file will also be created as | ||
| 959 | a symbolic link. | ||
| 960 | |||
| 961 | Otherwise, returns ``newmtime`` on success and ``False`` on failure. | ||
| 798 | """ | 962 | """ |
| 799 | 963 | ||
| 800 | #print "movefile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" | 964 | #print "movefile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" |
| @@ -885,9 +1049,24 @@ def movefile(src, dest, newmtime = None, sstat = None): | |||
| 885 | 1049 | ||
| 886 | def copyfile(src, dest, newmtime = None, sstat = None): | 1050 | def copyfile(src, dest, newmtime = None, sstat = None): |
| 887 | """ | 1051 | """ |
| 888 | Copies a file from src to dest, preserving all permissions and | 1052 | Copies a file from ``src`` to ``dest``, preserving all permissions and |
| 889 | attributes; mtime will be preserved even when moving across | 1053 | attributes; mtime will be preserved even when moving across |
| 890 | filesystems. Returns true on success and false on failure. | 1054 | filesystems. |
| 1055 | |||
| 1056 | Arguments: | ||
| 1057 | |||
| 1058 | - ``src``: Source file. | ||
| 1059 | - ``dest``: Destination file. | ||
| 1060 | - ``newmtime``: new mtime to be passed as float seconds since the epoch. | ||
| 1061 | - ``sstat``: os.stat_result to use for the destination file. | ||
| 1062 | |||
| 1063 | Returns an ``os.stat_result`` of the destination file if the | ||
| 1064 | source file is a symbolic link or the ``sstat`` argument represents a | ||
| 1065 | symbolic link - in which case the destination file will also be created as | ||
| 1066 | a symbolic link. | ||
| 1067 | |||
| 1068 | Otherwise, returns ``newmtime`` on success and ``False`` on failure. | ||
| 1069 | |||
| 891 | """ | 1070 | """ |
| 892 | #print "copyfile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" | 1071 | #print "copyfile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" |
| 893 | try: | 1072 | try: |
| @@ -965,10 +1144,16 @@ def copyfile(src, dest, newmtime = None, sstat = None): | |||
| 965 | 1144 | ||
| 966 | def break_hardlinks(src, sstat = None): | 1145 | def break_hardlinks(src, sstat = None): |
| 967 | """ | 1146 | """ |
| 968 | Ensures src is the only hardlink to this file. Other hardlinks, | 1147 | Ensures ``src`` is the only hardlink to this file. Other hardlinks, |
| 969 | if any, are not affected (other than in their st_nlink value, of | 1148 | if any, are not affected (other than in their st_nlink value, of |
| 970 | course). Returns true on success and false on failure. | 1149 | course). |
| 971 | 1150 | ||
| 1151 | Arguments: | ||
| 1152 | |||
| 1153 | - ``src``: source file path. | ||
| 1154 | - ``sstat``: os.stat_result to use when checking if the file is a link. | ||
| 1155 | |||
| 1156 | Returns ``True`` on success and ``False`` on failure. | ||
| 972 | """ | 1157 | """ |
| 973 | try: | 1158 | try: |
| 974 | if not sstat: | 1159 | if not sstat: |
| @@ -982,11 +1167,24 @@ def break_hardlinks(src, sstat = None): | |||
| 982 | 1167 | ||
| 983 | def which(path, item, direction = 0, history = False, executable=False): | 1168 | def which(path, item, direction = 0, history = False, executable=False): |
| 984 | """ | 1169 | """ |
| 985 | Locate `item` in the list of paths `path` (colon separated string like $PATH). | 1170 | Locate ``item`` in the list of paths ``path`` (colon separated string like |
| 986 | If `direction` is non-zero then the list is reversed. | 1171 | ``$PATH``). |
| 987 | If `history` is True then the list of candidates also returned as result,history. | 1172 | |
| 988 | If `executable` is True then the candidate has to be an executable file, | 1173 | Arguments: |
| 989 | otherwise the candidate simply has to exist. | 1174 | |
| 1175 | - ``path``: list of colon-separated paths. | ||
| 1176 | - ``item``: string to search for. | ||
| 1177 | - ``direction``: if non-zero then the list is reversed. | ||
| 1178 | - ``history``: if ``True`` then the list of candidates also returned as | ||
| 1179 | ``result,history`` where ``history`` is the list of previous path | ||
| 1180 | checked. | ||
| 1181 | - ``executable``: if ``True`` then the candidate defined by ``path`` has | ||
| 1182 | to be an executable file, otherwise if ``False`` the candidate simply | ||
| 1183 | has to exist. | ||
| 1184 | |||
| 1185 | Returns the item if found in the list of path, otherwise an empty string. | ||
| 1186 | If ``history`` is ``True``, return the list of previous path checked in a | ||
| 1187 | tuple with the found (or not found) item as ``(item, history)``. | ||
| 990 | """ | 1188 | """ |
| 991 | 1189 | ||
| 992 | if executable: | 1190 | if executable: |
| @@ -1017,6 +1215,8 @@ def which(path, item, direction = 0, history = False, executable=False): | |||
| 1017 | def umask(new_mask): | 1215 | def umask(new_mask): |
| 1018 | """ | 1216 | """ |
| 1019 | Context manager to set the umask to a specific mask, and restore it afterwards. | 1217 | Context manager to set the umask to a specific mask, and restore it afterwards. |
| 1218 | |||
| 1219 | No return value. | ||
| 1020 | """ | 1220 | """ |
| 1021 | current_mask = os.umask(new_mask) | 1221 | current_mask = os.umask(new_mask) |
| 1022 | try: | 1222 | try: |
| @@ -1027,7 +1227,17 @@ def umask(new_mask): | |||
| 1027 | def to_boolean(string, default=None): | 1227 | def to_boolean(string, default=None): |
| 1028 | """ | 1228 | """ |
| 1029 | Check input string and return boolean value True/False/None | 1229 | Check input string and return boolean value True/False/None |
| 1030 | depending upon the checks | 1230 | depending upon the checks. |
| 1231 | |||
| 1232 | Arguments: | ||
| 1233 | |||
| 1234 | - ``string``: input string. | ||
| 1235 | - ``default``: default return value if the input ``string`` is ``None``, | ||
| 1236 | ``0``, ``False`` or an empty string. | ||
| 1237 | |||
| 1238 | Returns ``True`` if the string is one of "y", "yes", "1", "true", ``False`` | ||
| 1239 | if the string is one of "n", "no", "0", or "false". Return ``default`` if | ||
| 1240 | the input ``string`` is ``None``, ``0``, ``False`` or an empty string. | ||
| 1031 | """ | 1241 | """ |
| 1032 | if not string: | 1242 | if not string: |
| 1033 | return default | 1243 | return default |
| @@ -1048,18 +1258,17 @@ def contains(variable, checkvalues, truevalue, falsevalue, d): | |||
| 1048 | 1258 | ||
| 1049 | Arguments: | 1259 | Arguments: |
| 1050 | 1260 | ||
| 1051 | variable -- the variable name. This will be fetched and expanded (using | 1261 | - ``variable``: the variable name. This will be fetched and expanded (using |
| 1052 | d.getVar(variable)) and then split into a set(). | 1262 | d.getVar(variable)) and then split into a set(). |
| 1263 | - ``checkvalues``: if this is a string it is split on whitespace into a set(), | ||
| 1264 | otherwise coerced directly into a set(). | ||
| 1265 | - ``truevalue``: the value to return if checkvalues is a subset of variable. | ||
| 1266 | - ``falsevalue``: the value to return if variable is empty or if checkvalues is | ||
| 1267 | not a subset of variable. | ||
| 1268 | - ``d``: the data store. | ||
| 1053 | 1269 | ||
| 1054 | checkvalues -- if this is a string it is split on whitespace into a set(), | 1270 | Returns ``True`` if the variable contains the values specified, ``False`` |
| 1055 | otherwise coerced directly into a set(). | 1271 | otherwise. |
| 1056 | |||
| 1057 | truevalue -- the value to return if checkvalues is a subset of variable. | ||
| 1058 | |||
| 1059 | falsevalue -- the value to return if variable is empty or if checkvalues is | ||
| 1060 | not a subset of variable. | ||
| 1061 | |||
| 1062 | d -- the data store. | ||
| 1063 | """ | 1272 | """ |
| 1064 | 1273 | ||
| 1065 | val = d.getVar(variable) | 1274 | val = d.getVar(variable) |
| @@ -1079,18 +1288,17 @@ def contains_any(variable, checkvalues, truevalue, falsevalue, d): | |||
| 1079 | 1288 | ||
| 1080 | Arguments: | 1289 | Arguments: |
| 1081 | 1290 | ||
| 1082 | variable -- the variable name. This will be fetched and expanded (using | 1291 | - ``variable``: the variable name. This will be fetched and expanded (using |
| 1083 | d.getVar(variable)) and then split into a set(). | 1292 | d.getVar(variable)) and then split into a set(). |
| 1084 | 1293 | - ``checkvalues``: if this is a string it is split on whitespace into a set(), | |
| 1085 | checkvalues -- if this is a string it is split on whitespace into a set(), | 1294 | otherwise coerced directly into a set(). |
| 1086 | otherwise coerced directly into a set(). | 1295 | - ``truevalue``: the value to return if checkvalues is a subset of variable. |
| 1087 | 1296 | - ``falsevalue``: the value to return if variable is empty or if checkvalues is | |
| 1088 | truevalue -- the value to return if checkvalues is a subset of variable. | 1297 | not a subset of variable. |
| 1298 | - ``d``: the data store. | ||
| 1089 | 1299 | ||
| 1090 | falsevalue -- the value to return if variable is empty or if checkvalues is | 1300 | Returns ``True`` if the variable contains any of the values specified, |
| 1091 | not a subset of variable. | 1301 | ``False`` otherwise. |
| 1092 | |||
| 1093 | d -- the data store. | ||
| 1094 | """ | 1302 | """ |
| 1095 | val = d.getVar(variable) | 1303 | val = d.getVar(variable) |
| 1096 | if not val: | 1304 | if not val: |
| @@ -1105,17 +1313,17 @@ def contains_any(variable, checkvalues, truevalue, falsevalue, d): | |||
| 1105 | return falsevalue | 1313 | return falsevalue |
| 1106 | 1314 | ||
| 1107 | def filter(variable, checkvalues, d): | 1315 | def filter(variable, checkvalues, d): |
| 1108 | """Return all words in the variable that are present in the checkvalues. | 1316 | """Return all words in the variable that are present in the ``checkvalues``. |
| 1109 | 1317 | ||
| 1110 | Arguments: | 1318 | Arguments: |
| 1111 | 1319 | ||
| 1112 | variable -- the variable name. This will be fetched and expanded (using | 1320 | - ``variable``: the variable name. This will be fetched and expanded (using |
| 1113 | d.getVar(variable)) and then split into a set(). | 1321 | d.getVar(variable)) and then split into a set(). |
| 1114 | 1322 | - ``checkvalues``: if this is a string it is split on whitespace into a set(), | |
| 1115 | checkvalues -- if this is a string it is split on whitespace into a set(), | 1323 | otherwise coerced directly into a set(). |
| 1116 | otherwise coerced directly into a set(). | 1324 | - ``d``: the data store. |
| 1117 | 1325 | ||
| 1118 | d -- the data store. | 1326 | Returns a list of string. |
| 1119 | """ | 1327 | """ |
| 1120 | 1328 | ||
| 1121 | val = d.getVar(variable) | 1329 | val = d.getVar(variable) |
| @@ -1131,8 +1339,27 @@ def filter(variable, checkvalues, d): | |||
| 1131 | 1339 | ||
| 1132 | def get_referenced_vars(start_expr, d): | 1340 | def get_referenced_vars(start_expr, d): |
| 1133 | """ | 1341 | """ |
| 1134 | :return: names of vars referenced in start_expr (recursively), in quasi-BFS order (variables within the same level | 1342 | Get the names of the variables referenced in a given expression. |
| 1135 | are ordered arbitrarily) | 1343 | |
| 1344 | Arguments: | ||
| 1345 | |||
| 1346 | - ``start_expr``: the expression where to look for variables references. | ||
| 1347 | |||
| 1348 | For example:: | ||
| 1349 | |||
| 1350 | ${VAR_A} string ${VAR_B} | ||
| 1351 | |||
| 1352 | Or:: | ||
| 1353 | |||
| 1354 | ${@d.getVar('VAR')} | ||
| 1355 | |||
| 1356 | If a variables makes references to other variables, the latter are also | ||
| 1357 | returned recursively. | ||
| 1358 | |||
| 1359 | - ``d``: the data store. | ||
| 1360 | |||
| 1361 | Returns the names of vars referenced in ``start_expr`` (recursively), in | ||
| 1362 | quasi-BFS order (variables within the same level are ordered arbitrarily). | ||
| 1136 | """ | 1363 | """ |
| 1137 | 1364 | ||
| 1138 | seen = set() | 1365 | seen = set() |
| @@ -1212,7 +1439,9 @@ def multiprocessingpool(*args, **kwargs): | |||
| 1212 | return multiprocessing.Pool(*args, **kwargs) | 1439 | return multiprocessing.Pool(*args, **kwargs) |
| 1213 | 1440 | ||
| 1214 | def exec_flat_python_func(func, *args, **kwargs): | 1441 | def exec_flat_python_func(func, *args, **kwargs): |
| 1215 | """Execute a flat python function (defined with def funcname(args):...)""" | 1442 | """Execute a flat python function (defined with ``def funcname(args): ...``) |
| 1443 | |||
| 1444 | Returns the return value of the function.""" | ||
| 1216 | # Prepare a small piece of python code which calls the requested function | 1445 | # Prepare a small piece of python code which calls the requested function |
| 1217 | # To do this we need to prepare two things - a set of variables we can use to pass | 1446 | # To do this we need to prepare two things - a set of variables we can use to pass |
| 1218 | # the values of arguments into the calling function, and the list of arguments for | 1447 | # the values of arguments into the calling function, and the list of arguments for |
| @@ -1238,48 +1467,57 @@ def edit_metadata(meta_lines, variables, varfunc, match_overrides=False): | |||
| 1238 | """Edit lines from a recipe or config file and modify one or more | 1467 | """Edit lines from a recipe or config file and modify one or more |
| 1239 | specified variable values set in the file using a specified callback | 1468 | specified variable values set in the file using a specified callback |
| 1240 | function. Lines are expected to have trailing newlines. | 1469 | function. Lines are expected to have trailing newlines. |
| 1241 | Parameters: | 1470 | |
| 1242 | meta_lines: lines from the file; can be a list or an iterable | 1471 | Arguments: |
| 1243 | (e.g. file pointer) | 1472 | |
| 1244 | variables: a list of variable names to look for. Functions | 1473 | - ``meta_lines``: lines from the file; can be a list or an iterable |
| 1245 | may also be specified, but must be specified with '()' at | 1474 | (e.g. file pointer) |
| 1246 | the end of the name. Note that the function doesn't have | 1475 | - ``variables``: a list of variable names to look for. Functions |
| 1247 | any intrinsic understanding of :append, :prepend, :remove, | 1476 | may also be specified, but must be specified with ``()`` at |
| 1248 | or overrides, so these are considered as part of the name. | 1477 | the end of the name. Note that the function doesn't have |
| 1249 | These values go into a regular expression, so regular | 1478 | any intrinsic understanding of ``:append``, ``:prepend``, ``:remove``, |
| 1250 | expression syntax is allowed. | 1479 | or overrides, so these are considered as part of the name. |
| 1251 | varfunc: callback function called for every variable matching | 1480 | These values go into a regular expression, so regular |
| 1252 | one of the entries in the variables parameter. The function | 1481 | expression syntax is allowed. |
| 1253 | should take four arguments: | 1482 | - ``varfunc``: callback function called for every variable matching |
| 1254 | varname: name of variable matched | 1483 | one of the entries in the variables parameter. |
| 1255 | origvalue: current value in file | 1484 | |
| 1256 | op: the operator (e.g. '+=') | 1485 | The function should take four arguments: |
| 1257 | newlines: list of lines up to this point. You can use | 1486 | |
| 1258 | this to prepend lines before this variable setting | 1487 | - ``varname``: name of variable matched |
| 1259 | if you wish. | 1488 | - ``origvalue``: current value in file |
| 1260 | and should return a four-element tuple: | 1489 | - ``op``: the operator (e.g. ``+=``) |
| 1261 | newvalue: new value to substitute in, or None to drop | 1490 | - ``newlines``: list of lines up to this point. You can use |
| 1262 | the variable setting entirely. (If the removal | 1491 | this to prepend lines before this variable setting |
| 1263 | results in two consecutive blank lines, one of the | 1492 | if you wish. |
| 1264 | blank lines will also be dropped). | 1493 | |
| 1265 | newop: the operator to use - if you specify None here, | 1494 | And should return a four-element tuple: |
| 1266 | the original operation will be used. | 1495 | |
| 1267 | indent: number of spaces to indent multi-line entries, | 1496 | - ``newvalue``: new value to substitute in, or ``None`` to drop |
| 1268 | or -1 to indent up to the level of the assignment | 1497 | the variable setting entirely. (If the removal |
| 1269 | and opening quote, or a string to use as the indent. | 1498 | results in two consecutive blank lines, one of the |
| 1270 | minbreak: True to allow the first element of a | 1499 | blank lines will also be dropped). |
| 1271 | multi-line value to continue on the same line as | 1500 | - ``newop``: the operator to use - if you specify ``None`` here, |
| 1272 | the assignment, False to indent before the first | 1501 | the original operation will be used. |
| 1273 | element. | 1502 | - ``indent``: number of spaces to indent multi-line entries, |
| 1274 | To clarify, if you wish not to change the value, then you | 1503 | or ``-1`` to indent up to the level of the assignment |
| 1275 | would return like this: return origvalue, None, 0, True | 1504 | and opening quote, or a string to use as the indent. |
| 1276 | match_overrides: True to match items with _overrides on the end, | 1505 | - ``minbreak``: ``True`` to allow the first element of a |
| 1277 | False otherwise | 1506 | multi-line value to continue on the same line as |
| 1507 | the assignment, ``False`` to indent before the first | ||
| 1508 | element. | ||
| 1509 | |||
| 1510 | To clarify, if you wish not to change the value, then you | ||
| 1511 | would return like this:: | ||
| 1512 | |||
| 1513 | return origvalue, None, 0, True | ||
| 1514 | - ``match_overrides``: True to match items with _overrides on the end, | ||
| 1515 | False otherwise | ||
| 1516 | |||
| 1278 | Returns a tuple: | 1517 | Returns a tuple: |
| 1279 | updated: | 1518 | |
| 1280 | True if changes were made, False otherwise. | 1519 | - ``updated``: ``True`` if changes were made, ``False`` otherwise. |
| 1281 | newlines: | 1520 | - ``newlines``: Lines after processing. |
| 1282 | Lines after processing | ||
| 1283 | """ | 1521 | """ |
| 1284 | 1522 | ||
| 1285 | var_res = {} | 1523 | var_res = {} |
| @@ -1423,12 +1661,13 @@ def edit_metadata(meta_lines, variables, varfunc, match_overrides=False): | |||
| 1423 | 1661 | ||
| 1424 | 1662 | ||
| 1425 | def edit_metadata_file(meta_file, variables, varfunc): | 1663 | def edit_metadata_file(meta_file, variables, varfunc): |
| 1426 | """Edit a recipe or config file and modify one or more specified | 1664 | """Edit a recipe or configuration file and modify one or more specified |
| 1427 | variable values set in the file using a specified callback function. | 1665 | variable values set in the file using a specified callback function. |
| 1428 | The file is only written to if the value(s) actually change. | 1666 | The file is only written to if the value(s) actually change. |
| 1429 | This is basically the file version of edit_metadata(), see that | 1667 | This is basically the file version of ``bb.utils.edit_metadata()``, see that |
| 1430 | function's description for parameter/usage information. | 1668 | function's description for parameter/usage information. |
| 1431 | Returns True if the file was written to, False otherwise. | 1669 | |
| 1670 | Returns ``True`` if the file was written to, ``False`` otherwise. | ||
| 1432 | """ | 1671 | """ |
| 1433 | with open(meta_file, 'r') as f: | 1672 | with open(meta_file, 'r') as f: |
| 1434 | (updated, newlines) = edit_metadata(f, variables, varfunc) | 1673 | (updated, newlines) = edit_metadata(f, variables, varfunc) |
| @@ -1439,20 +1678,24 @@ def edit_metadata_file(meta_file, variables, varfunc): | |||
| 1439 | 1678 | ||
| 1440 | 1679 | ||
| 1441 | def edit_bblayers_conf(bblayers_conf, add, remove, edit_cb=None): | 1680 | def edit_bblayers_conf(bblayers_conf, add, remove, edit_cb=None): |
| 1442 | """Edit bblayers.conf, adding and/or removing layers | 1681 | """Edit ``bblayers.conf``, adding and/or removing layers. |
| 1443 | Parameters: | 1682 | |
| 1444 | bblayers_conf: path to bblayers.conf file to edit | 1683 | Arguments: |
| 1445 | add: layer path (or list of layer paths) to add; None or empty | 1684 | |
| 1446 | list to add nothing | 1685 | - ``bblayers_conf``: path to ``bblayers.conf`` file to edit |
| 1447 | remove: layer path (or list of layer paths) to remove; None or | 1686 | - ``add``: layer path (or list of layer paths) to add; ``None`` or empty |
| 1448 | empty list to remove nothing | 1687 | list to add nothing |
| 1449 | edit_cb: optional callback function that will be called after | 1688 | - ``remove``: layer path (or list of layer paths) to remove; ``None`` or |
| 1450 | processing adds/removes once per existing entry. | 1689 | empty list to remove nothing |
| 1690 | - ``edit_cb``: optional callback function that will be called | ||
| 1691 | after processing adds/removes once per existing entry. | ||
| 1692 | |||
| 1451 | Returns a tuple: | 1693 | Returns a tuple: |
| 1452 | notadded: list of layers specified to be added but weren't | 1694 | |
| 1453 | (because they were already in the list) | 1695 | - ``notadded``: list of layers specified to be added but weren't |
| 1454 | notremoved: list of layers that were specified to be removed | 1696 | (because they were already in the list) |
| 1455 | but weren't (because they weren't in the list) | 1697 | - ``notremoved``: list of layers that were specified to be removed |
| 1698 | but weren't (because they weren't in the list) | ||
| 1456 | """ | 1699 | """ |
| 1457 | 1700 | ||
| 1458 | def remove_trailing_sep(pth): | 1701 | def remove_trailing_sep(pth): |
| @@ -1572,7 +1815,22 @@ def get_collection_res(d): | |||
| 1572 | 1815 | ||
| 1573 | 1816 | ||
| 1574 | def get_file_layer(filename, d, collection_res={}): | 1817 | def get_file_layer(filename, d, collection_res={}): |
| 1575 | """Determine the collection (as defined by a layer's layer.conf file) containing the specified file""" | 1818 | """Determine the collection (or layer name, as defined by a layer's |
| 1819 | ``layer.conf`` file) containing the specified file. | ||
| 1820 | |||
| 1821 | Arguments: | ||
| 1822 | |||
| 1823 | - ``filename``: the filename to look for. | ||
| 1824 | - ``d``: the data store. | ||
| 1825 | - ``collection_res``: dictionary with the layer names as keys and file | ||
| 1826 | patterns to match as defined with the BBFILE_COLLECTIONS and | ||
| 1827 | BBFILE_PATTERN variables respectively. The return value of | ||
| 1828 | ``bb.utils.get_collection_res()`` is the default if this variable is | ||
| 1829 | not specified. | ||
| 1830 | |||
| 1831 | Returns the layer name containing the file. If multiple layers contain the | ||
| 1832 | file, the last matching layer name from collection_res is returned. | ||
| 1833 | """ | ||
| 1576 | if not collection_res: | 1834 | if not collection_res: |
| 1577 | collection_res = get_collection_res(d) | 1835 | collection_res = get_collection_res(d) |
| 1578 | 1836 | ||
| @@ -1610,7 +1868,13 @@ class PrCtlError(Exception): | |||
| 1610 | 1868 | ||
| 1611 | def signal_on_parent_exit(signame): | 1869 | def signal_on_parent_exit(signame): |
| 1612 | """ | 1870 | """ |
| 1613 | Trigger signame to be sent when the parent process dies | 1871 | Trigger ``signame`` to be sent when the parent process dies. |
| 1872 | |||
| 1873 | Arguments: | ||
| 1874 | |||
| 1875 | - ``signame``: name of the signal. See ``man signal``. | ||
| 1876 | |||
| 1877 | No return value. | ||
| 1614 | """ | 1878 | """ |
| 1615 | signum = getattr(signal, signame) | 1879 | signum = getattr(signal, signame) |
| 1616 | # http://linux.die.net/man/2/prctl | 1880 | # http://linux.die.net/man/2/prctl |
| @@ -1697,6 +1961,13 @@ def disable_network(uid=None, gid=None): | |||
| 1697 | Disable networking in the current process if the kernel supports it, else | 1961 | Disable networking in the current process if the kernel supports it, else |
| 1698 | just return after logging to debug. To do this we need to create a new user | 1962 | just return after logging to debug. To do this we need to create a new user |
| 1699 | namespace, then map back to the original uid/gid. | 1963 | namespace, then map back to the original uid/gid. |
| 1964 | |||
| 1965 | Arguments: | ||
| 1966 | |||
| 1967 | - ``uid``: original user id. | ||
| 1968 | - ``gid``: original user group id. | ||
| 1969 | |||
| 1970 | No return value. | ||
| 1700 | """ | 1971 | """ |
| 1701 | libc = ctypes.CDLL('libc.so.6') | 1972 | libc = ctypes.CDLL('libc.so.6') |
| 1702 | 1973 | ||
| @@ -1766,9 +2037,14 @@ class LogCatcher(logging.Handler): | |||
| 1766 | 2037 | ||
| 1767 | def is_semver(version): | 2038 | def is_semver(version): |
| 1768 | """ | 2039 | """ |
| 1769 | Is the version string following the semver semantic? | 2040 | Arguments: |
| 2041 | |||
| 2042 | - ``version``: the version string. | ||
| 1770 | 2043 | ||
| 1771 | https://semver.org/spec/v2.0.0.html | 2044 | Returns ``True`` if the version string follow semantic versioning, ``False`` |
| 2045 | otherwise. | ||
| 2046 | |||
| 2047 | See https://semver.org/spec/v2.0.0.html. | ||
| 1772 | """ | 2048 | """ |
| 1773 | regex = re.compile( | 2049 | regex = re.compile( |
| 1774 | r""" | 2050 | r""" |
| @@ -1806,6 +2082,8 @@ def rename(src, dst): | |||
| 1806 | def environment(**envvars): | 2082 | def environment(**envvars): |
| 1807 | """ | 2083 | """ |
| 1808 | Context manager to selectively update the environment with the specified mapping. | 2084 | Context manager to selectively update the environment with the specified mapping. |
| 2085 | |||
| 2086 | No return value. | ||
| 1809 | """ | 2087 | """ |
| 1810 | backup = dict(os.environ) | 2088 | backup = dict(os.environ) |
| 1811 | try: | 2089 | try: |
| @@ -1822,6 +2100,13 @@ def is_local_uid(uid=''): | |||
| 1822 | """ | 2100 | """ |
| 1823 | Check whether uid is a local one or not. | 2101 | Check whether uid is a local one or not. |
| 1824 | Can't use pwd module since it gets all UIDs, not local ones only. | 2102 | Can't use pwd module since it gets all UIDs, not local ones only. |
| 2103 | |||
| 2104 | Arguments: | ||
| 2105 | |||
| 2106 | - ``uid``: user id. If not specified the user id is determined from | ||
| 2107 | ``os.getuid()``. | ||
| 2108 | |||
| 2109 | Returns ``True`` is the user id is local, ``False`` otherwise. | ||
| 1825 | """ | 2110 | """ |
| 1826 | if not uid: | 2111 | if not uid: |
| 1827 | uid = os.getuid() | 2112 | uid = os.getuid() |
| @@ -1836,7 +2121,7 @@ def is_local_uid(uid=''): | |||
| 1836 | 2121 | ||
| 1837 | def mkstemp(suffix=None, prefix=None, dir=None, text=False): | 2122 | def mkstemp(suffix=None, prefix=None, dir=None, text=False): |
| 1838 | """ | 2123 | """ |
| 1839 | Generates a unique filename, independent of time. | 2124 | Generates a unique temporary file, independent of time. |
| 1840 | 2125 | ||
| 1841 | mkstemp() in glibc (at least) generates unique file names based on the | 2126 | mkstemp() in glibc (at least) generates unique file names based on the |
| 1842 | current system time. When combined with highly parallel builds, and | 2127 | current system time. When combined with highly parallel builds, and |
| @@ -1845,6 +2130,18 @@ def mkstemp(suffix=None, prefix=None, dir=None, text=False): | |||
| 1845 | 2130 | ||
| 1846 | This function adds additional entropy to the file name so that a collision | 2131 | This function adds additional entropy to the file name so that a collision |
| 1847 | is independent of time and thus extremely unlikely. | 2132 | is independent of time and thus extremely unlikely. |
| 2133 | |||
| 2134 | Arguments: | ||
| 2135 | |||
| 2136 | - ``suffix``: filename suffix. | ||
| 2137 | - ``prefix``: filename prefix. | ||
| 2138 | - ``dir``: directory where the file will be created. | ||
| 2139 | - ``text``: if ``True``, the file is opened in text mode. | ||
| 2140 | |||
| 2141 | Returns a tuple containing: | ||
| 2142 | |||
| 2143 | - the file descriptor for the created file | ||
| 2144 | - the name of the file. | ||
| 1848 | """ | 2145 | """ |
| 1849 | entropy = "".join(random.choices("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", k=20)) | 2146 | entropy = "".join(random.choices("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", k=20)) |
| 1850 | if prefix: | 2147 | if prefix: |
| @@ -1855,12 +2152,20 @@ def mkstemp(suffix=None, prefix=None, dir=None, text=False): | |||
| 1855 | 2152 | ||
| 1856 | def path_is_descendant(descendant, ancestor): | 2153 | def path_is_descendant(descendant, ancestor): |
| 1857 | """ | 2154 | """ |
| 1858 | Returns True if the path `descendant` is a descendant of `ancestor` | 2155 | Returns ``True`` if the path ``descendant`` is a descendant of ``ancestor`` |
| 1859 | (including being equivalent to `ancestor` itself). Otherwise returns False. | 2156 | (including being equivalent to ``ancestor`` itself). Otherwise returns |
| 2157 | ``False``. | ||
| 2158 | |||
| 1860 | Correctly accounts for symlinks, bind mounts, etc. by using | 2159 | Correctly accounts for symlinks, bind mounts, etc. by using |
| 1861 | os.path.samestat() to compare paths | 2160 | ``os.path.samestat()`` to compare paths. |
| 2161 | |||
| 2162 | May raise any exception that ``os.stat()`` raises. | ||
| 2163 | |||
| 2164 | Arguments: | ||
| 1862 | 2165 | ||
| 1863 | May raise any exception that os.stat() raises | 2166 | - ``descendant``: path to check for being an ancestor. |
| 2167 | - ``ancestor``: path to the ancestor ``descendant`` will be checked | ||
| 2168 | against. | ||
| 1864 | """ | 2169 | """ |
| 1865 | 2170 | ||
| 1866 | ancestor_stat = os.stat(ancestor) | 2171 | ancestor_stat = os.stat(ancestor) |
