mirror of
				https://github.com/enpaul/tox-poetry-installer.git
				synced 2025-10-29 07:10:09 +00:00 
			
		
		
		
	Compare commits
	
		
			40 Commits
		
	
	
		
			0.8.3
			...
			779dd8c56f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 779dd8c56f | |||
| 3399bbecc2 | |||
| dd61f8c40f | |||
| 447475ebe0 | |||
| d711a17596 | |||
| 4f69c8b3b2 | |||
| bd102605b6 | |||
| 469cb251cf | |||
| 41ac5423f9 | |||
| 3388553ee0 | |||
| 52f34cb317 | |||
| 4c609770f1 | |||
| d5650f0562 | |||
| 4261d45218 | |||
| d0842456cb | |||
| b631a962b2 | |||
| 453b575159 | |||
| 50e1aaddcd | |||
|  | d0efbd06b3 | ||
| c435f1af69 | |||
| 817ae28a23 | |||
| 12c4ec62f2 | |||
|  | 73ddd43284 | ||
|  | a181da95b3 | ||
|  | e8ce2f391b | ||
|  | c8fd6e4fc0 | ||
|  | 22012d4452 | ||
|  | 17d0272089 | ||
|  | b54bf44dc5 | ||
| 17885b50f7 | |||
| 72c719c26c | |||
| 5f30656683 | |||
| b3a5e869ac | |||
| afc94a5e01 | |||
| a9d29aea9f | |||
| 45e33b7d27 | |||
| ff3e1603d2 | |||
| fb65fa812e | |||
| f08a18728e | |||
| 07027181ce | 
							
								
								
									
										2
									
								
								.github/scripts/setup-env.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/scripts/setup-env.sh
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ | ||||
| set -e; | ||||
|  | ||||
| CI_CACHE=$HOME/.cache; | ||||
| POETRY_VERSION=1.1.12; | ||||
| POETRY_VERSION=1.3.2; | ||||
|  | ||||
| mkdir --parents "$CI_CACHE"; | ||||
|  | ||||
|   | ||||
							
								
								
									
										35
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -7,12 +7,11 @@ on: | ||||
|     branches: ["devel"] | ||||
| jobs: | ||||
|   Test: | ||||
|     name: Python ${{ matrix.python.version }} | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       matrix: | ||||
|         python: | ||||
|           - version: "3.6" | ||||
|             toxenv: py36 | ||||
|           - version: "3.7" | ||||
|             toxenv: py37 | ||||
|           - version: "3.8" | ||||
| @@ -21,15 +20,20 @@ jobs: | ||||
|             toxenv: py39 | ||||
|           - version: "3.10" | ||||
|             toxenv: py310 | ||||
|           - version: "3.11" | ||||
|             toxenv: py311 | ||||
|       fail-fast: true | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|  | ||||
|       - name: Install Python ${{ matrix.python.version }} | ||||
|         uses: actions/setup-python@v1 | ||||
|         uses: actions/setup-python@v4 | ||||
|         with: | ||||
|           python-version: ${{ matrix.python.version }} | ||||
|  | ||||
|       - name: Configure Job Cache | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/.cache/pip | ||||
| @@ -39,38 +43,49 @@ jobs: | ||||
|           # will be invalidated, and thus all packages will be redownloaded, if the | ||||
|           # lockfile is updated | ||||
|           key: ${{ runner.os }}-${{ matrix.python.toxenv }}-${{ hashFiles('**/poetry.lock') }} | ||||
|  | ||||
|       - name: Configure Path | ||||
|         run: echo "$HOME/.local/bin" >> $GITHUB_PATH | ||||
|  | ||||
|       - name: Configure Environment | ||||
|         run: .github/scripts/setup-env.sh | ||||
|  | ||||
|       - name: Run Toxenv ${{ matrix.python.toxenv }} | ||||
|         run: poetry run tox -e ${{ matrix.python.toxenv }} | ||||
|  | ||||
|   Check: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - name: Install Python 3.8 | ||||
|         uses: actions/setup-python@v1 | ||||
|  | ||||
|       - name: Install Python 3.10 | ||||
|         uses: actions/setup-python@v4 | ||||
|         with: | ||||
|           python-version: 3.8 | ||||
|           python-version: "3.10" | ||||
|  | ||||
|       - name: Configure Job Cache | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/.cache/pip | ||||
|             ~/.cache/pypoetry/cache | ||||
|             ~/.poetry | ||||
|           # Hardcoded 'py38' slug here lets this cache piggyback on the 'py38' cache | ||||
|           # Hardcoded 'py310' slug here lets this cache piggyback on the 'py310' cache | ||||
|           # that is generated for the tests above | ||||
|           key: ${{ runner.os }}-py38-${{ hashFiles('**/poetry.lock') }} | ||||
|           key: ${{ runner.os }}-py310-${{ hashFiles('**/poetry.lock') }} | ||||
|  | ||||
|       - name: Configure Path | ||||
|         run: echo "$HOME/.local/bin" >> $GITHUB_PATH | ||||
|  | ||||
|       - name: Configure Environment | ||||
|         run: .github/scripts/setup-env.sh | ||||
|  | ||||
|       - name: Run Static Analysis Checks | ||||
|         run: poetry run tox -e static | ||||
|  | ||||
|       - name: Run Static Analysis Checks (Tests) | ||||
|         run: poetry run tox -e static-tests | ||||
|  | ||||
|       - name: Run Security Checks | ||||
|         run: poetry run tox -e security | ||||
|   | ||||
							
								
								
									
										400
									
								
								.pylintrc
									
									
									
									
									
								
							
							
						
						
									
										400
									
								
								.pylintrc
									
									
									
									
									
								
							| @@ -1,46 +1,5 @@ | ||||
| [MASTER] | ||||
|  | ||||
| # A comma-separated list of package or module names from where C extensions may | ||||
| # be loaded. Extensions are loading into the active Python interpreter and may | ||||
| # run arbitrary code | ||||
| extension-pkg-whitelist= | ||||
|  | ||||
| # Add files or directories to the blacklist. They should be base names, not | ||||
| # paths. | ||||
| ignore= | ||||
|  | ||||
| # Add files or directories matching the regex patterns to the blacklist. The | ||||
| # regex matches against base names, not paths. | ||||
| ignore-patterns= | ||||
|  | ||||
| # Python code to execute, usually for sys.path manipulation such as | ||||
| # pygtk.require(). | ||||
| #init-hook= | ||||
|  | ||||
| # Use multiple processes to speed up Pylint. | ||||
| jobs=1 | ||||
|  | ||||
| # List of plugins (as comma separated values of python modules names) to load, | ||||
| # usually to register additional checkers. | ||||
| load-plugins= | ||||
|  | ||||
| # Pickle collected data for later comparisons. | ||||
| persistent=yes | ||||
|  | ||||
| # Specify a configuration file. | ||||
| #rcfile= | ||||
|  | ||||
| # Allow loading of arbitrary C extensions. Extensions are imported into the | ||||
| # active Python interpreter and may run arbitrary code. | ||||
| unsafe-load-any-extension=no | ||||
|  | ||||
|  | ||||
| [MESSAGES CONTROL] | ||||
|  | ||||
| # Only show warnings with the listed confidence levels. Leave empty to show | ||||
| # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED | ||||
| confidence= | ||||
|  | ||||
| # Disable the message, report, category or checker with the given id(s). You | ||||
| # can either give multiple identifiers separated by comma (,) or put this | ||||
| # option multiple times (only on the command line, not in the configuration | ||||
| @@ -50,378 +9,47 @@ confidence= | ||||
| # --enable=similarities". If you want to run only the classes checker, but have | ||||
| # no Warning level messages displayed, use"--disable=all --enable=classes | ||||
| # --disable=W" | ||||
| disable=logging-fstring-interpolation, logging-format-interpolation, bad-continuation, line-too-long | ||||
| #print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call, | ||||
|  | ||||
| # Enable the message, report, category or checker with the given id(s). You can | ||||
| # either give multiple identifier separated by comma (,) or put this option | ||||
| # multiple time (only on the command line, not in the configuration file where | ||||
| # it should appear only once). See also the "--disable" option for examples. | ||||
| enable= | ||||
| disable=logging-fstring-interpolation | ||||
|         ,logging-format-interpolation | ||||
|         ,bad-continuation | ||||
|         ,line-too-long | ||||
|         ,ungrouped-imports | ||||
|         ,typecheck | ||||
|         ,wrong-import-order | ||||
|         ,wrong-import-position | ||||
|  | ||||
|  | ||||
| [REPORTS] | ||||
|  | ||||
| # Python expression which should return a note less than 10 (10 is the highest | ||||
| # note). You have access to the variables errors warning, statement which | ||||
| # respectively contain the number of errors / warnings messages and the total | ||||
| # number of statements analyzed. This is used by the global evaluation report | ||||
| # (RP0004). | ||||
| evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) | ||||
|  | ||||
| # Template used to display messages. This is a python new-style format string | ||||
| # used to format the message information. See doc for all details | ||||
| #msg-template= | ||||
|  | ||||
| # Set the output format. Available formats are text, parseable, colorized, json | ||||
| # and msvs (visual studio).You can also give a reporter class, eg | ||||
| # mypackage.mymodule.MyReporterClass. | ||||
| output-format=text | ||||
|  | ||||
| # Tells whether to display a full report or only the messages | ||||
| reports=no | ||||
|  | ||||
| # Activate the evaluation score. | ||||
| score=yes | ||||
|  | ||||
|  | ||||
| [REFACTORING] | ||||
|  | ||||
| # Maximum number of nested blocks for function / method body | ||||
| max-nested-blocks=5 | ||||
| output-format=colorized | ||||
|  | ||||
|  | ||||
| [BASIC] | ||||
|  | ||||
| # Naming hint for argument names | ||||
| argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Regular expression matching correct argument names | ||||
| argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Naming hint for attribute names | ||||
| attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Regular expression matching correct attribute names | ||||
| attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Bad variable names which should always be refused, separated by a comma | ||||
| bad-names=foo,bar,baz,toto,tutu,tata | ||||
|  | ||||
| # Naming hint for class attribute names | ||||
| class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ | ||||
|  | ||||
| # Regular expression matching correct class attribute names | ||||
| class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ | ||||
|  | ||||
| # Naming hint for class names | ||||
| class-name-hint=[A-Z_][a-zA-Z0-9]+$ | ||||
|  | ||||
| # Regular expression matching correct class names | ||||
| class-rgx=[A-Z_][a-zA-Z0-9]+$ | ||||
|  | ||||
| # Naming hint for constant names | ||||
| const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ | ||||
|  | ||||
| # Regular expression matching correct constant names | ||||
| const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ | ||||
|  | ||||
| # Minimum line length for functions/classes that require docstrings, shorter | ||||
| # ones are exempt. | ||||
| docstring-min-length=-1 | ||||
|  | ||||
| # Naming hint for function names | ||||
| function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Regular expression matching correct function names | ||||
| function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Good variable names which should always be accepted, separated by a comma | ||||
| good-names=_,ip,ap | ||||
|  | ||||
| # Include a hint for the correct naming format with invalid-name | ||||
| include-naming-hint=no | ||||
|  | ||||
| # Naming hint for inline iteration names | ||||
| inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ | ||||
|  | ||||
| # Regular expression matching correct inline iteration names | ||||
| inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ | ||||
|  | ||||
| # Naming hint for method names | ||||
| method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Regular expression matching correct method names | ||||
| method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Naming hint for module names | ||||
| module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ | ||||
|  | ||||
| # Regular expression matching correct module names | ||||
| module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ | ||||
|  | ||||
| # Colon-delimited sets of names that determine each other's naming style when | ||||
| # the name regexes allow several styles. | ||||
| name-group= | ||||
|  | ||||
| # Regular expression which should only match function or class names that do | ||||
| # not require a docstring. | ||||
| no-docstring-rgx=^_ | ||||
|  | ||||
| # List of decorators that produce properties, such as abc.abstractproperty. Add | ||||
| # to this list to register other decorators that produce valid properties. | ||||
| property-classes=abc.abstractproperty | ||||
|  | ||||
| # Naming hint for variable names | ||||
| variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
|  | ||||
| # Regular expression matching correct variable names | ||||
| variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ | ||||
| good-names=_,ip,T | ||||
|  | ||||
|  | ||||
| [MISCELLANEOUS] | ||||
|  | ||||
| # List of note tags to take in consideration, separated by a comma. | ||||
| #notes=FIXME,XXX,TODO | ||||
| # Not FIXME or TODO | ||||
| notes=XXX | ||||
|  | ||||
|  | ||||
| [LOGGING] | ||||
|  | ||||
| # Logging modules to check that the string format arguments are in logging | ||||
| # function parameter format | ||||
| logging-modules=logging | ||||
|  | ||||
|  | ||||
| [SIMILARITIES] | ||||
|  | ||||
| # Ignore comments when computing similarities. | ||||
| ignore-comments=yes | ||||
|  | ||||
| # Ignore docstrings when computing similarities. | ||||
| ignore-docstrings=yes | ||||
|  | ||||
| # Ignore imports when computing similarities. | ||||
| ignore-imports=yes | ||||
|  | ||||
| # Ignore function signatures when computing similarities. | ||||
| ignore-signatures=yes | ||||
|  | ||||
| # Minimum lines number of a similarity. | ||||
| min-similarity-lines=10 | ||||
|  | ||||
|  | ||||
| [VARIABLES] | ||||
|  | ||||
| # List of additional names supposed to be defined in builtins. Remember that | ||||
| # you should avoid to define new builtins when possible. | ||||
| additional-builtins= | ||||
|  | ||||
| # Tells whether unused global variables should be treated as a violation. | ||||
| allow-global-unused-variables=yes | ||||
|  | ||||
| # List of strings which can identify a callback function by name. A callback | ||||
| # name must start or end with one of those strings. | ||||
| callbacks=cb_,_cb | ||||
|  | ||||
| # A regular expression matching the name of dummy variables (i.e. expectedly | ||||
| # not used). | ||||
| dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ | ||||
|  | ||||
| # Argument names that match this expression will be ignored. Default to name | ||||
| # with leading underscore | ||||
| ignored-argument-names=_.*|^ignored_|^unused_|^fxt_ | ||||
|  | ||||
| # Tells whether we should check for unused import in __init__ files. | ||||
| init-import=no | ||||
|  | ||||
| # List of qualified module names which can have objects that can redefine | ||||
| # builtins. | ||||
| redefining-builtins-modules=six.moves,future.builtins | ||||
|  | ||||
|  | ||||
| [SPELLING] | ||||
|  | ||||
| # Spelling dictionary name. Available dictionaries: none. To make it working | ||||
| # install python-enchant package. | ||||
| spelling-dict= | ||||
|  | ||||
| # List of comma separated words that should not be checked. | ||||
| spelling-ignore-words= | ||||
|  | ||||
| # A path to a file that contains private dictionary; one word per line. | ||||
| spelling-private-dict-file= | ||||
|  | ||||
| # Tells whether to store unknown words to indicated private dictionary in | ||||
| # --spelling-private-dict-file option instead of raising a message. | ||||
| spelling-store-unknown-words=no | ||||
|  | ||||
|  | ||||
| [FORMAT] | ||||
|  | ||||
| # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. | ||||
| expected-line-ending-format= | ||||
|  | ||||
| # Regexp for a line that is allowed to be longer than the limit. | ||||
| ignore-long-lines=^\s*(# )?<?https?://\S+>?$ | ||||
|  | ||||
| # Number of spaces of indent required inside a hanging  or continued line. | ||||
| indent-after-paren=4 | ||||
|  | ||||
| # String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1 | ||||
| # tab). | ||||
| indent-string='    ' | ||||
|  | ||||
| # Maximum number of characters on a single line. | ||||
| max-line-length=100 | ||||
|  | ||||
| # Maximum number of lines in a module | ||||
| max-module-lines=1000 | ||||
|  | ||||
| # List of optional constructs for which whitespace checking is disabled. `dict- | ||||
| # separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}. | ||||
| # `trailing-comma` allows a space between comma and closing bracket: (a, ). | ||||
| # `empty-line` allows space-only lines. | ||||
| no-space-check=trailing-comma,dict-separator | ||||
|  | ||||
| # Allow the body of a class to be on the same line as the declaration if body | ||||
| # contains single statement. | ||||
| single-line-class-stmt=no | ||||
|  | ||||
| # Allow the body of an if to be on the same line as the test if there is no | ||||
| # else. | ||||
| single-line-if-stmt=no | ||||
|  | ||||
|  | ||||
| [TYPECHECK] | ||||
|  | ||||
| # List of decorators that produce context managers, such as | ||||
| # contextlib.contextmanager. Add to this list to register other decorators that | ||||
| # produce valid context managers. | ||||
| contextmanager-decorators=contextlib.contextmanager | ||||
|  | ||||
| # List of members which are set dynamically and missed by pylint inference | ||||
| # system, and so shouldn't trigger E1101 when accessed. Python regular | ||||
| # expressions are accepted. | ||||
| generated-members= | ||||
|  | ||||
| # Tells whether missing members accessed in mixin class should be ignored. A | ||||
| # mixin class is detected if its name ends with "mixin" (case insensitive). | ||||
| ignore-mixin-members=yes | ||||
|  | ||||
| # This flag controls whether pylint should warn about no-member and similar | ||||
| # checks whenever an opaque object is returned when inferring. The inference | ||||
| # can return multiple potential results while evaluating a Python object, but | ||||
| # some branches might not be evaluated, which results in partial inference. In | ||||
| # that case, it might be useful to still emit no-member and other checks for | ||||
| # the rest of the inferred objects. | ||||
| ignore-on-opaque-inference=yes | ||||
|  | ||||
| # List of class names for which member attributes should not be checked (useful | ||||
| # for classes with dynamically set attributes). This supports the use of | ||||
| # qualified names. | ||||
| ignored-classes=optparse.Values,thread._local,_thread._local | ||||
|  | ||||
| # List of module names for which member attributes should not be checked | ||||
| # (useful for modules/projects where namespaces are manipulated during runtime | ||||
| # and thus existing member attributes cannot be deduced by static analysis. It | ||||
| # supports qualified module names, as well as Unix pattern matching. | ||||
| ignored-modules= | ||||
|  | ||||
| # Show a hint with possible names when a member name was not found. The aspect | ||||
| # of finding the hint is based on edit distance. | ||||
| missing-member-hint=yes | ||||
|  | ||||
| # The minimum edit distance a name should have in order to be considered a | ||||
| # similar match for a missing member name. | ||||
| missing-member-hint-distance=1 | ||||
|  | ||||
| # The total number of similar names that should be taken in consideration when | ||||
| # showing a hint for a missing member. | ||||
| missing-member-max-choices=1 | ||||
|  | ||||
|  | ||||
| [CLASSES] | ||||
|  | ||||
| # List of method names used to declare (i.e. assign) instance attributes. | ||||
| defining-attr-methods=__init__,__new__,setUp | ||||
|  | ||||
| # List of member names, which should be excluded from the protected access | ||||
| # warning. | ||||
| exclude-protected=_asdict,_fields,_replace,_source,_make | ||||
|  | ||||
| # List of valid names for the first argument in a class method. | ||||
| valid-classmethod-first-arg=cls | ||||
|  | ||||
| # List of valid names for the first argument in a metaclass class method. | ||||
| valid-metaclass-classmethod-first-arg=mcs | ||||
|  | ||||
|  | ||||
| [IMPORTS] | ||||
|  | ||||
| # Allow wildcard imports from modules that define __all__. | ||||
| allow-wildcard-with-all=no | ||||
|  | ||||
| # Analyse import fallback blocks. This can be used to support both Python 2 and | ||||
| # 3 compatible code, which means that the block might have code that exists | ||||
| # only in one or another interpreter, leading to false positives when analysed. | ||||
| analyse-fallback-blocks=no | ||||
|  | ||||
| # Deprecated modules which should not be used, separated by a comma | ||||
| deprecated-modules=regsub,TERMIOS,Bastion,rexec | ||||
|  | ||||
| # Create a graph of external dependencies in the given file (report RP0402 must | ||||
| # not be disabled) | ||||
| ext-import-graph= | ||||
|  | ||||
| # Create a graph of every (i.e. internal and external) dependencies in the | ||||
| # given file (report RP0402 must not be disabled) | ||||
| import-graph= | ||||
|  | ||||
| # Create a graph of internal dependencies in the given file (report RP0402 must | ||||
| # not be disabled) | ||||
| int-import-graph= | ||||
|  | ||||
| # Force import order to recognize a module as part of the standard | ||||
| # compatibility libraries. | ||||
| known-standard-library= | ||||
|  | ||||
| # Force import order to recognize a module as part of a third party library. | ||||
| known-third-party=enchant | ||||
|  | ||||
|  | ||||
| [DESIGN] | ||||
|  | ||||
| # Maximum number of arguments for function / method | ||||
| max-args=7 | ||||
|  | ||||
| # Maximum number of attributes for a class (see R0902). | ||||
| max-attributes=7 | ||||
|  | ||||
| # Maximum number of boolean expressions in a if statement | ||||
| max-bool-expr=5 | ||||
|  | ||||
| # Maximum number of branch for function / method body | ||||
| max-branches=12 | ||||
|  | ||||
| # Maximum number of locals for function / method body | ||||
| max-locals=15 | ||||
|  | ||||
| # Maximum number of parents for a class (see R0901). | ||||
| max-parents=7 | ||||
|  | ||||
| # Maximum number of public methods for a class (see R0904). | ||||
| max-public-methods=20 | ||||
|  | ||||
| # Maximum number of return / yield for function / method body | ||||
| max-returns=6 | ||||
|  | ||||
| # Maximum number of statements in function / method body | ||||
| max-statements=50 | ||||
|  | ||||
| # Minimum number of public methods for a class (see R0903). | ||||
| min-public-methods=2 | ||||
|  | ||||
|  | ||||
| [EXCEPTIONS] | ||||
|  | ||||
| # Exceptions that will emit a warning when being caught. Defaults to | ||||
| # "Exception" | ||||
| overgeneral-exceptions=Exception | ||||
|   | ||||
							
								
								
									
										53
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,6 +2,57 @@ | ||||
|  | ||||
| See also: [Github Release Page](https://github.com/enpaul/tox-poetry-installer/releases). | ||||
|  | ||||
| ## Version 0.10.1 | ||||
|  | ||||
| View this release on: | ||||
| [Github](https://github.com/enpaul/tox-poetry-installer/releases/tag/0.10.1), | ||||
| [PyPI](https://pypi.org/project/tox-poetry-installer/0.10.1/) | ||||
|  | ||||
| - Add PyPI classifier for Python-3.11 compatibility | ||||
| - Add CI support for Python-3.11 | ||||
| - Add support for Poetry-1.3.x (#83) | ||||
|  | ||||
| ## Version 0.10.0 | ||||
|  | ||||
| View this release on: | ||||
| [Github](https://github.com/enpaul/tox-poetry-installer/releases/tag/0.10.0), | ||||
| [PyPI](https://pypi.org/project/tox-poetry-installer/0.10.0/) | ||||
|  | ||||
| - Add `poetry_dep_groups` option to support installing groups of Poetry dependencies. | ||||
|   Contributed by [Oshmoun](https://github.com/oshmoun) (#76) | ||||
| - Deprecate `install_dev_deps` option | ||||
|  | ||||
| ## Version 0.9.0 | ||||
|  | ||||
| View this release on: | ||||
| [Github](https://github.com/enpaul/tox-poetry-installer/releases/tag/0.9.0), | ||||
| [PyPI](https://pypi.org/project/tox-poetry-installer/0.9.0/) | ||||
|  | ||||
| - Add support for Poetry-1.2.x. Contributed by [Justin Wood](https://github.com/Callek) | ||||
|   (#73) | ||||
| - Update Black formatting to stable release version | ||||
| - Remove support for Python-3.6 | ||||
| - Remove support for Poetry-1.1.x | ||||
| - Fix installing dependencies multiple times when transient dependencies are duplicated in | ||||
|   the dependency tree | ||||
|  | ||||
| ## Version 0.8.5 | ||||
|  | ||||
| View this release on: | ||||
| [Github](https://github.com/enpaul/tox-poetry-installer/releases/tag/0.8.5), | ||||
| [PyPI](https://pypi.org/project/tox-poetry-installer/0.8.5/) | ||||
|  | ||||
| - Fix Poetry version specification supporting the incompatible Poetry-1.2.0 release | ||||
|  | ||||
| ## Version 0.8.4 | ||||
|  | ||||
| View this release on: | ||||
| [Github](https://github.com/enpaul/tox-poetry-installer/releases/tag/0.8.4), | ||||
| [PyPI](https://pypi.org/project/tox-poetry-installer/0.8.4/) | ||||
|  | ||||
| - Fix issue where incompatible package versions were selected for installation when multiple | ||||
|   package versions were in the lockfile | ||||
|  | ||||
| ## Version 0.8.3 | ||||
|  | ||||
| View this release on: | ||||
| @@ -18,7 +69,7 @@ View this release on: | ||||
|  | ||||
| - Improve debug-level logging for package installation, and time how long installing each | ||||
|   package takes. Contributed by [Rebecca | ||||
|   Turner](https://github.com/9999years). | ||||
|   Turner](https://github.com/9999years) (#63). | ||||
| - Fix crash caused by the package-under-test depending on Poetry's unsafe dependencies ([#65](https://github.com/enpaul/tox-poetry-installer/issues/65)) | ||||
|  | ||||
| ## Version 0.8.1 | ||||
|   | ||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -33,7 +33,7 @@ test: ## Run the project testsuite(s) | ||||
| 	poetry run tox --recreate | ||||
|  | ||||
| dev: ## Create the local dev environment | ||||
| 	poetry install -E poetry | ||||
| 	poetry install --extras poetry --sync | ||||
| 	poetry run pre-commit install | ||||
|  | ||||
| publish: test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set) | ||||
|   | ||||
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							| @@ -34,16 +34,16 @@ See the | ||||
| [Changelog](https://github.com/enpaul/tox-poetry-installer/blob/devel/CHANGELOG.md) for | ||||
| release history. | ||||
|  | ||||
| *See also: [official Tox plugins](https://tox.readthedocs.io/en/latest/plugins.html), [Poetry-Dev-Dependencies Tox plugin](https://github.com/sinoroc/tox-poetry-dev-dependencies), [Poetry Tox plugin](https://github.com/tkukushkin/tox-poetry)* | ||||
| *See also: [official Tox plugins](https://tox.readthedocs.io/en/latest/plugins.html), [Poetry Tox plugin](https://github.com/tkukushkin/tox-poetry)* | ||||
|  | ||||
| ## Feature Overview | ||||
|  | ||||
| - Manage package versions in exactly one place and with exactly one tool: Poetry. | ||||
| - Ensure CI/CD and other automation tools are using the same package versions that you are | ||||
|   in your local development environment. | ||||
| - Add only the packages you need to a Tox test environment, instead of everything in your | ||||
|   lockfile. | ||||
| - Directly integrate with Poetry, re-using your existing package indexes and credentials | ||||
| - Add only the packages or custom groups you need to a Tox test environment, instead of | ||||
|   everything in your lockfile. | ||||
| - Directly integrate with Poetry, re-using your existing package indexes and credentials, | ||||
|   with no additional configuration. | ||||
| - Wherever possible, built-in Tox config options are always respected and their behavior | ||||
|   kept consistent. | ||||
| @@ -151,19 +151,23 @@ commands = ... | ||||
| > the child environment with a different value. | ||||
|  | ||||
| Alternatively, we can skip specifying all of our dependencies for a test environment in | ||||
| the Tox config and just install all of our Poetry dev-dependencies automatically: | ||||
| the Tox config and install Poetry dependency groups directly: | ||||
|  | ||||
| ```ini | ||||
| [testenv] | ||||
| description = Some very cool tests | ||||
| require_locked_deps = true | ||||
| install_dev_deps = true | ||||
| poetry_dep_groups = | ||||
|     dev | ||||
| commands = ... | ||||
| ``` | ||||
|  | ||||
| > **Note:** Setting `install_dev_deps = true` on an environment that also installs the | ||||
| > **Note:** Setting `poetry_dep_groups = [dev]` on an environment that also installs the | ||||
| > project package is functionally equivalent to running `poetry install`. | ||||
|  | ||||
| > **Note:** The `install_dev_deps` configuration option is deprecated. See [Configuration | ||||
| > Options](#configuration-options) for more information. | ||||
|  | ||||
| Finally, we can also install an unlocked dependency (a dependency which doesn't take its | ||||
| version from the Poetry lockfile) into the test environment alongside the locked ones. We | ||||
| need to remove the `require_locked_deps = true` option, otherwise the environment will | ||||
| @@ -198,9 +202,13 @@ configuration section. | ||||
| | :--------------------- | :-----: | :-----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||||
| | `locked_deps`          |  List   |  `[]`   | Names of packages to install to the test environment from the Poetry lockfile. Transient dependencies (packages required by these dependencies) are automatically included.                                                                                                                                                                                          | | ||||
| | `require_locked_deps`  | Boolean |  False  | Whether the plugin should block attempts to install unlocked dependencies to the test environment. If enabled, then the [`tox_testenv_install_deps`](https://tox.readthedocs.io/en/latest/plugins.html#tox.hookspecs.tox_testenv_install_deps) plugin hook will be intercepted and an error will be raised if the test environment has the `deps` option configured. | | ||||
| | `install_dev_deps`     | Boolean |  False  | Whether all of the Poetry dev-dependencies should be installed to the test environment.                                                                                                                                                                                                                                                                              | | ||||
| | `install_project_deps` | Boolean |  True   | Whether all of the Poetry primary dependencies for the project package should be installed to the test environment.                                                                                                                                                                                                                                                  | | ||||
| | `require_poetry`       | Boolean |  False  | Whether Tox should be forced to fail if the plugin cannot import Poetry locally. If `False` then the plugin will be skipped for the test environment if Poetry cannot be imported. If `True` then the plugin will force the environment to error and the Tox run to fail.                                                                                            | | ||||
| | `poetry_dep_groups`    |  List   |  `[]`   | Names of Poetry dependency groups specified in `pyproject.toml` to install to the test environment.                                                                                                                                                                                                                                                                  | | ||||
|  | ||||
| > **Note:** The `install_dev_deps` configuration option is deprecated and will be removed in | ||||
| > version 1.0.0. Please set `poetry_dep_groups = [dev]` in `tox.ini` for environments that | ||||
| > install the development dependencies. | ||||
|  | ||||
| ### Runtime Options | ||||
|  | ||||
| @@ -230,7 +238,7 @@ error will be set to one of the "Status" values below to indicate what the error | ||||
| | `LockedDepVersionConflictError` | Indicates that an item in the `locked_deps` config option includes a [PEP-508 version specifier](https://www.python.org/dev/peps/pep-0508/#grammar) (ex: `pytest >=6.0, <6.1`).                                                 | | ||||
| | `LockedDepNotFoundError`        | Indicates that an item specified in the `locked_deps` config option does not match the name of a package in the Poetry lockfile.                                                                                                | | ||||
| | `LockedDepsRequiredError`       | Indicates that a test environment with the `require_locked_deps` config option set to `true` also specified unlocked dependencies using the [`deps`](https://tox.readthedocs.io/en/latest/config.html#conf-deps) config option. | | ||||
| | `PoetryNotInstalledError`       | Indicates that the `poetry` module could not be imported under the current runtime environment, and the `--require-poetry` flag was provided.                                                                                   | | ||||
| | `PoetryNotInstalledError`       | Indicates that the `poetry` module could not be imported under the current runtime environment, and `require_poetry = true` was specified.                                                                                      | | ||||
| | `RequiresUnsafeDepError`        | Indicates that the package-under-test depends on a package that Poetry has classified as unsafe and cannot be installed.                                                                                                        | | ||||
|  | ||||
| > **Note:** One or more of these errors can be caused by the `pyproject.toml` being out of | ||||
| @@ -353,7 +361,7 @@ are tracked on [Github](https://github.com/enpaul/tox-poetry-installer/releases) | ||||
|   and [open a pull request](https://github.com/enpaul/tox-poetry-installer/compare). | ||||
|  | ||||
| Developing this project requires [Python 3.7+](https://www.python.org/downloads/) and | ||||
| [Poetry 1.0](https://python-poetry.org/docs/#installation) or later. GNU Make can | ||||
| [Poetry 1.2](https://python-poetry.org/docs/#installation) or later. GNU Make can | ||||
| optionally be used to quickly setup a local development environment, but this is not | ||||
| required. | ||||
|  | ||||
| @@ -368,18 +376,11 @@ git clone git@github.com:enpaul/tox-poetry-installer.git | ||||
|  | ||||
| cd tox-poetry-installer/ | ||||
|  | ||||
| # Create and configure the local development environment... | ||||
| # ...with make: | ||||
| # Create and configure the local development environment | ||||
| make dev | ||||
| # ...manually: | ||||
| poetry install -E poetry --remove-untracked | ||||
| poetry run pre-commit install | ||||
|  | ||||
| # Run tests and CI locally... | ||||
| # ...with make: | ||||
| # Run tests and CI locally | ||||
| make test | ||||
| # ...manually: | ||||
| poetry run tox --recreate | ||||
|  | ||||
| # See additional make targets | ||||
| make help | ||||
|   | ||||
							
								
								
									
										3071
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3071
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,6 +1,6 @@ | ||||
| [tool.poetry] | ||||
| name = "tox-poetry-installer" | ||||
| version = "0.8.3" | ||||
| version = "0.10.1" | ||||
| license = "MIT" | ||||
| authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] | ||||
| description = "A plugin for Tox that lets you install test environment dependencies from the Poetry lockfile" | ||||
| @@ -23,11 +23,11 @@ classifiers = [ | ||||
|   "Natural Language :: English", | ||||
|   "Operating System :: OS Independent", | ||||
|   "Programming Language :: Python :: 3", | ||||
|   "Programming Language :: Python :: 3.6", | ||||
|   "Programming Language :: Python :: 3.7", | ||||
|   "Programming Language :: Python :: 3.8", | ||||
|   "Programming Language :: Python :: 3.9", | ||||
|   "Programming Language :: Python :: 3.10", | ||||
|   "Programming Language :: Python :: 3.11", | ||||
|   "Programming Language :: Python :: Implementation :: CPython", | ||||
| ] | ||||
|  | ||||
| @@ -35,33 +35,39 @@ classifiers = [ | ||||
| poetry_installer = "tox_poetry_installer" | ||||
|  | ||||
| [tool.poetry.extras] | ||||
| poetry = ["poetry"] | ||||
| poetry = ["poetry", "cleo"] | ||||
|  | ||||
| [tool.poetry.dependencies] | ||||
| python = "^3.6.1" | ||||
| poetry = {version = "^1.0.0", optional = true} | ||||
| poetry-core = "^1.0.0" | ||||
| python = "^3.7" | ||||
| cleo = {version = ">=1.0,<3.0", optional = true} | ||||
| poetry = {version = "^1.2.0", optional = true} | ||||
| poetry-core = "^1.1.0" | ||||
| tox = "^3.8.0" | ||||
|  | ||||
| [tool.poetry.dev-dependencies] | ||||
| [tool.poetry.group.dev.dependencies] | ||||
| bandit = "^1.6.2" | ||||
| black = {version = "^21.12b0", allow-prereleases = true, python = "^3.7"} | ||||
| black = "^22.3.0" | ||||
| blacken-docs = "^1.8.0" | ||||
| ipython = { version = "^7.18.1", python = "^3.7" } | ||||
| ipython = {version = "^8.10.1", python = "^3.8"} | ||||
| mdformat = "^0.6" | ||||
| mdformat-gfm = "^0.2" | ||||
| mypy = "^0.930" | ||||
| pre-commit = "^2.7.1" | ||||
| pre-commit-hooks = "^3.3.0" | ||||
| pylint = "^2.4.4" | ||||
| pylint = "^2.13.0" | ||||
| pytest = "^6.0.2" | ||||
| pytest-cov = "^2.10.1" | ||||
| reorder-python-imports = "^2.3.5" | ||||
| safety = "^1.9.0" | ||||
| safety = "^2.2.0" | ||||
| toml = "^0.10.1" | ||||
| tox = "^3.20.0" | ||||
| types-toml = "^0.10.1" | ||||
| # This is a workaround for this issue with the Poetry export | ||||
| # plugin which was blocking the 'security' CI check: | ||||
| # | ||||
| # https://github.com/python-poetry/poetry-plugin-export/issues/176 | ||||
| virtualenv = ">=20.15,<20.16" | ||||
|  | ||||
| [build-system] | ||||
| requires = ["poetry-core>=1.0.0"] | ||||
| requires = ["poetry-core>=1.1.0"] | ||||
| build-backend = "poetry.core.masonry.api" | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import poetry.installation.pip_installer | ||||
| import poetry.utils.env | ||||
| import pytest | ||||
| import tox | ||||
| from poetry.core.packages import Package as PoetryPackage | ||||
| from poetry.core.packages.package import Package as PoetryPackage | ||||
|  | ||||
| from tox_poetry_installer import utilities | ||||
|  | ||||
| @@ -31,6 +31,10 @@ class MockVirtualEnv: | ||||
|     def is_valid_for_marker(*args, **kwargs): | ||||
|         return True | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_version_info(): | ||||
|         return (1, 2, 3) | ||||
|  | ||||
|  | ||||
| class MockPipInstaller: | ||||
|     """Mock class for the :class:`poetry.installation.pip_installer.PipInstaller`""" | ||||
|   | ||||
| @@ -6,15 +6,15 @@ from poetry.factory import Factory | ||||
|  | ||||
| from .fixtures import mock_poetry_factory | ||||
| from .fixtures import mock_venv | ||||
| from tox_poetry_installer import datatypes | ||||
| from tox_poetry_installer import installer | ||||
| from tox_poetry_installer import utilities | ||||
|  | ||||
|  | ||||
| def test_deduplication(mock_venv, mock_poetry_factory): | ||||
|     """Test that the installer does not install duplicate dependencies""" | ||||
|     poetry = Factory().create_poetry(None) | ||||
|     packages: datatypes.PackageMap = { | ||||
|         item.name: item for item in poetry.locker.locked_repository(False).packages | ||||
|     packages: utilities.PackageMap = { | ||||
|         item.name: item for item in poetry.locker.locked_repository().packages | ||||
|     } | ||||
|  | ||||
|     venv = tox.venv.VirtualEnv() | ||||
| @@ -28,8 +28,8 @@ def test_deduplication(mock_venv, mock_poetry_factory): | ||||
| def test_parallelization(mock_venv, mock_poetry_factory): | ||||
|     """Test that behavior is consistent between parallel and non-parallel usage""" | ||||
|     poetry = Factory().create_poetry(None) | ||||
|     packages: datatypes.PackageMap = { | ||||
|         item.name: item for item in poetry.locker.locked_repository(False).packages | ||||
|     packages: utilities.PackageMap = { | ||||
|         item.name: item for item in poetry.locker.locked_repository().packages | ||||
|     } | ||||
|  | ||||
|     to_install = [ | ||||
|   | ||||
| @@ -7,7 +7,6 @@ from poetry.puzzle.provider import Provider | ||||
| from .fixtures import mock_poetry_factory | ||||
| from .fixtures import mock_venv | ||||
| from tox_poetry_installer import constants | ||||
| from tox_poetry_installer import datatypes | ||||
| from tox_poetry_installer import exceptions | ||||
| from tox_poetry_installer import utilities | ||||
|  | ||||
| @@ -58,17 +57,15 @@ def test_functional(mock_poetry_factory, mock_venv): | ||||
|     is always the last in the returned list. | ||||
|     """ | ||||
|     pypoetry = poetry.factory.Factory().create_poetry(None) | ||||
|     packages: datatypes.PackageMap = { | ||||
|         item.name: item for item in pypoetry.locker.locked_repository(False).packages | ||||
|     } | ||||
|     packages = utilities.build_package_map(pypoetry) | ||||
|     venv = poetry.utils.env.VirtualEnv()  # pylint: disable=no-value-for-parameter | ||||
|  | ||||
|     requests_requires = [ | ||||
|         packages["certifi"], | ||||
|         packages["chardet"], | ||||
|         packages["idna"], | ||||
|         packages["urllib3"], | ||||
|         packages["requests"], | ||||
|         packages["certifi"][0], | ||||
|         packages["chardet"][0], | ||||
|         packages["idna"][0], | ||||
|         packages["urllib3"][0], | ||||
|         packages["requests"][0], | ||||
|     ] | ||||
|  | ||||
|     transients = utilities.identify_transients("requests", packages, venv) | ||||
| @@ -76,7 +73,7 @@ def test_functional(mock_poetry_factory, mock_venv): | ||||
|     assert all((item in requests_requires) for item in transients) | ||||
|     assert all((item in transients) for item in requests_requires) | ||||
|  | ||||
|     for package in [packages["requests"], packages["tox"], packages["flask"]]: | ||||
|         transients = utilities.identify_transients(package, packages, venv) | ||||
|     for package in [packages["requests"][0], packages["tox"][0], packages["flask"][0]]: | ||||
|         transients = utilities.identify_transients(package.name, packages, venv) | ||||
|         assert transients[-1] == package | ||||
|         assert len(transients) == len(set(transients)) | ||||
|   | ||||
							
								
								
									
										15
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								tox.ini
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| [tox] | ||||
| envlist = py36, py37, py38, py39, py310, static, static-tests, security | ||||
| envlist = py37, py38, py39, py310, py311, static, static-tests, security | ||||
| isolated_build = true | ||||
| skip_missing_interpreters = true | ||||
|  | ||||
| @@ -21,7 +21,7 @@ commands = | ||||
|  | ||||
| [testenv:static] | ||||
| description = Static formatting and quality enforcement | ||||
| basepython = python3.8 | ||||
| basepython = python3.10 | ||||
| platform = linux | ||||
| ignore_errors = true | ||||
| locked_deps = | ||||
| @@ -46,7 +46,7 @@ commands = | ||||
|  | ||||
| [testenv:static-tests] | ||||
| description = Static formatting and quality enforcement for the tests | ||||
| basepython = python3.8 | ||||
| basepython = python3.10 | ||||
| platform = linux | ||||
| ignore_errors = true | ||||
| locked_deps = | ||||
| @@ -63,7 +63,7 @@ commands = | ||||
|  | ||||
| [testenv:security] | ||||
| description = Security checks | ||||
| basepython = python3.8 | ||||
| basepython = python3.10 | ||||
| platform = linux | ||||
| ignore_errors = true | ||||
| skip_install = true | ||||
| @@ -83,7 +83,10 @@ commands = | ||||
|       --format requirements.txt \ | ||||
|       --output {envtmpdir}/requirements.txt \ | ||||
|       --without-hashes \ | ||||
|       --dev | ||||
|       --with dev \ | ||||
|       --extras poetry | ||||
|     safety check \ | ||||
|       --file {envtmpdir}/requirements.txt \ | ||||
|       --json | ||||
|       --output text \ | ||||
|       # https://github.com/pytest-dev/py/issues/287 | ||||
|       --ignore 51457 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # pylint: disable=missing-docstring | ||||
| __title__ = "tox-poetry-installer" | ||||
| __summary__ = "A plugin for Tox that lets you install test environment dependencies from the Poetry lockfile" | ||||
| __version__ = "0.8.3" | ||||
| __version__ = "0.10.1" | ||||
| __url__ = "https://github.com/enpaul/tox-poetry-installer/" | ||||
| __license__ = "MIT" | ||||
| __authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] | ||||
|   | ||||
| @@ -28,9 +28,9 @@ from tox_poetry_installer import exceptions | ||||
|  | ||||
|  | ||||
| try: | ||||
|     from cleo.io.null_io import NullIO | ||||
|     from poetry.factory import Factory | ||||
|     from poetry.installation.pip_installer import PipInstaller | ||||
|     from poetry.io.null_io import NullIO | ||||
|     from poetry.poetry import Poetry | ||||
|     from poetry.utils.env import VirtualEnv | ||||
| except ImportError: | ||||
|   | ||||
| @@ -20,7 +20,8 @@ PEP508_VERSION_DELIMITERS: Tuple[str, ...] = ("~=", "==", "!=", ">", "<") | ||||
| REPORTER_PREFIX: str = f"{__about__.__title__}:" | ||||
|  | ||||
| # Internal list of packages that poetry has deemed unsafe and are excluded from the lockfile | ||||
| UNSAFE_PACKAGES: Set[str] = {"distribute", "pip", "setuptools", "wheel"} | ||||
| # TODO: This functionality is no longer needed, should remove in a future update. | ||||
| UNSAFE_PACKAGES: Set[str] = set() | ||||
|  | ||||
| # Number of threads to use for installing dependencies by default | ||||
| DEFAULT_INSTALL_THREADS: int = 10 | ||||
|   | ||||
| @@ -1,8 +0,0 @@ | ||||
| """Definitions for typehints/containers used by the plugin""" | ||||
| from typing import Dict | ||||
|  | ||||
| from poetry.core.packages import Package as PoetryPackage | ||||
|  | ||||
|  | ||||
| # Map of package names to the package object | ||||
| PackageMap = Dict[str, PoetryPackage] | ||||
| @@ -4,6 +4,7 @@ All implementations of tox hooks are defined here, as well as any single-use hel | ||||
| specifically related to implementing the hooks (to keep the size/readability of the hook functions | ||||
| themselves manageable). | ||||
| """ | ||||
| from itertools import chain | ||||
| from typing import Optional | ||||
|  | ||||
| import tox | ||||
| @@ -17,7 +18,6 @@ from tox_poetry_installer import exceptions | ||||
| from tox_poetry_installer import installer | ||||
| from tox_poetry_installer import logger | ||||
| from tox_poetry_installer import utilities | ||||
| from tox_poetry_installer.datatypes import PackageMap | ||||
|  | ||||
|  | ||||
| def _postprocess_install_project_deps( | ||||
| @@ -115,7 +115,14 @@ def tox_addoption(parser: ToxParser): | ||||
|         name="install_dev_deps", | ||||
|         type="bool", | ||||
|         default=False, | ||||
|         help="Automatically install all Poetry development dependencies to the environment", | ||||
|         help="(deprecated) Automatically install all Poetry development dependencies to the environment", | ||||
|     ) | ||||
|  | ||||
|     parser.add_testenv_attribute( | ||||
|         name="poetry_dep_groups", | ||||
|         type="line-list", | ||||
|         default=[], | ||||
|         help="List of Poetry dependency groups to install to the environment", | ||||
|     ) | ||||
|  | ||||
|     parser.add_testenv_attribute( | ||||
| @@ -186,10 +193,7 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional | ||||
|                 f"Unlocked dependencies '{venv.envconfig.deps}' specified for environment '{venv.name}' which requires locked dependencies" | ||||
|             ) | ||||
|  | ||||
|         packages: PackageMap = { | ||||
|             package.name: package | ||||
|             for package in poetry.locker.locked_repository(True).packages | ||||
|         } | ||||
|         packages = utilities.build_package_map(poetry) | ||||
|  | ||||
|         if venv.envconfig.install_dev_deps: | ||||
|             dev_deps = utilities.find_dev_deps(packages, virtualenv, poetry) | ||||
| @@ -200,6 +204,20 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional | ||||
|             dev_deps = [] | ||||
|             logger.info("Env does not install development dependencies, skipping") | ||||
|  | ||||
|         group_deps = utilities.dedupe_packages( | ||||
|             list( | ||||
|                 chain( | ||||
|                     *[ | ||||
|                         utilities.find_group_deps(group, packages, virtualenv, poetry) | ||||
|                         for group in venv.envconfig.poetry_dep_groups | ||||
|                     ] | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|         logger.info( | ||||
|             f"Identified {len(group_deps)} group dependencies to install to env" | ||||
|         ) | ||||
|  | ||||
|         env_deps = utilities.find_additional_deps( | ||||
|             packages, virtualenv, poetry, venv.envconfig.locked_deps | ||||
|         ) | ||||
| @@ -235,7 +253,9 @@ def tox_testenv_install_deps(venv: ToxVirtualEnv, action: ToxAction) -> Optional | ||||
|         logger.error(f"Internal plugin error: {err}") | ||||
|         raise err | ||||
|  | ||||
|     dependencies = dev_deps + env_deps + project_deps | ||||
|     dependencies = utilities.dedupe_packages( | ||||
|         dev_deps + group_deps + env_deps + project_deps | ||||
|     ) | ||||
|     if ( | ||||
|         venv.envconfig.config.option.parallel_install_threads | ||||
|         != constants.DEFAULT_INSTALL_THREADS | ||||
|   | ||||
| @@ -6,10 +6,10 @@ import concurrent.futures | ||||
| import contextlib | ||||
| import typing | ||||
| from datetime import datetime | ||||
| from typing import Sequence | ||||
| from typing import Collection | ||||
| from typing import Set | ||||
|  | ||||
| from poetry.core.packages import Package as PoetryPackage | ||||
| from poetry.core.packages.package import Package as PoetryPackage | ||||
| from tox.venv import VirtualEnv as ToxVirtualEnv | ||||
|  | ||||
| from tox_poetry_installer import logger | ||||
| @@ -22,7 +22,7 @@ if typing.TYPE_CHECKING: | ||||
| def install( | ||||
|     poetry: "_poetry.Poetry", | ||||
|     venv: ToxVirtualEnv, | ||||
|     packages: Sequence[PoetryPackage], | ||||
|     packages: Collection[PoetryPackage], | ||||
|     parallels: int = 0, | ||||
| ): | ||||
|     """Install a bunch of packages to a virtualenv | ||||
|   | ||||
| @@ -2,27 +2,30 @@ | ||||
| # Silence this one globally to support the internal function imports for the proxied poetry module. | ||||
| # See the docstring in 'tox_poetry_installer._poetry' for more context. | ||||
| # pylint: disable=import-outside-toplevel | ||||
| import collections | ||||
| import typing | ||||
| from pathlib import Path | ||||
| from typing import Dict | ||||
| from typing import List | ||||
| from typing import Sequence | ||||
| from typing import Set | ||||
| from typing import Union | ||||
|  | ||||
| from poetry.core.packages import Dependency as PoetryDependency | ||||
| from poetry.core.packages import Package as PoetryPackage | ||||
| from poetry.core.packages.dependency import Dependency as PoetryDependency | ||||
| from poetry.core.packages.package import Package as PoetryPackage | ||||
| from tox.action import Action as ToxAction | ||||
| from tox.venv import VirtualEnv as ToxVirtualEnv | ||||
|  | ||||
| from tox_poetry_installer import constants | ||||
| from tox_poetry_installer import exceptions | ||||
| from tox_poetry_installer import logger | ||||
| from tox_poetry_installer.datatypes import PackageMap | ||||
|  | ||||
| if typing.TYPE_CHECKING: | ||||
|     from tox_poetry_installer import _poetry | ||||
|  | ||||
|  | ||||
| PackageMap = Dict[str, List[PoetryPackage]] | ||||
|  | ||||
|  | ||||
| def check_preconditions(venv: ToxVirtualEnv, action: ToxAction) -> "_poetry.Poetry": | ||||
|     """Check that the local project environment meets expectations""" | ||||
|     # Skip running the plugin for the provisioning environment. The provisioned environment, | ||||
| @@ -56,6 +59,13 @@ def check_preconditions(venv: ToxVirtualEnv, action: ToxAction) -> "_poetry.Poet | ||||
|             "be removed in version 1.0.0. Please use the '--parallel-install-threads' option." | ||||
|         ) | ||||
|  | ||||
|     if venv.envconfig.install_dev_deps: | ||||
|         logger.warning( | ||||
|             "DEPRECATION: The 'install_dev_deps' option is deprecated and will be removed in " | ||||
|             "version 1.0.0. Please update test environments that install development dependencies " | ||||
|             "to set the 'poetry_dev_groups = [dev]' option in tox.ini" | ||||
|         ) | ||||
|  | ||||
|     from tox_poetry_installer import _poetry | ||||
|  | ||||
|     try: | ||||
| @@ -82,15 +92,28 @@ def convert_virtualenv(venv: ToxVirtualEnv) -> "_poetry.VirtualEnv": | ||||
|     return _poetry.VirtualEnv(path=Path(venv.envconfig.envdir)) | ||||
|  | ||||
|  | ||||
| def build_package_map(poetry: "_poetry.Poetry") -> PackageMap: | ||||
|     """Build the mapping of package names to objects | ||||
|  | ||||
|     :param poetry: Populated poetry object to load locked packages from | ||||
|     :returns: Mapping of package names to Poetry package objects | ||||
|     """ | ||||
|     packages = collections.defaultdict(list) | ||||
|     for package in poetry.locker.locked_repository().packages: | ||||
|         packages[package.name].append(package) | ||||
|  | ||||
|     return packages | ||||
|  | ||||
|  | ||||
| def identify_transients( | ||||
|     dep: Union[PoetryDependency, str], | ||||
|     dep_name: str, | ||||
|     packages: PackageMap, | ||||
|     venv: "_poetry.VirtualEnv", | ||||
|     allow_missing: Sequence[str] = (), | ||||
| ) -> List[PoetryPackage]: | ||||
|     """Using a pool of packages, identify all transient dependencies of a given package name | ||||
|  | ||||
|     :param dep: Either the Poetry dependency or the dependency's bare package name to recursively | ||||
|     :param dep_name: Either the Poetry dependency or the dependency's bare package name to recursively | ||||
|                      identify the transient dependencies of | ||||
|     :param packages: All packages from the lockfile to use for identifying dependency relationships. | ||||
|     :param venv: Poetry virtual environment to use for package compatibility checks | ||||
| @@ -102,53 +125,64 @@ def identify_transients( | ||||
|     .. note:: The package corresponding to the dependency specified by the ``dep`` parameter will | ||||
|               be included in the returned list of packages. | ||||
|     """ | ||||
|     transients: List[PoetryPackage] = [] | ||||
|     searched: Set[str] = set() | ||||
|  | ||||
|     def _deps_of_dep(transient: PoetryDependency): | ||||
|     def _transients(transient: PoetryDependency) -> List[PoetryPackage]: | ||||
|         searched.add(transient.name) | ||||
|  | ||||
|         if venv.is_valid_for_marker(transient.marker): | ||||
|             for requirement in packages[transient.name].requires: | ||||
|         results: List[PoetryPackage] = [] | ||||
|         for option in packages[transient.name]: | ||||
|             if venv.is_valid_for_marker(option.to_dependency().marker): | ||||
|                 for requirement in option.requires: | ||||
|                     if requirement.name not in searched: | ||||
|                     _deps_of_dep(requirement) | ||||
|             logger.debug(f"Including {transient} for installation") | ||||
|             transients.append(packages[transient.name]) | ||||
|                         results += _transients(requirement) | ||||
|                 logger.debug(f"Including {option} for installation") | ||||
|                 results.append(option) | ||||
|                 break | ||||
|         else: | ||||
|             logger.debug(f"Skipping {transient}: package requires {transient.marker}") | ||||
|             logger.debug( | ||||
|                 f"Skipping {transient.name}: target python version is {'.'.join([str(item) for item in venv.get_version_info()])} but package requires {transient.marker}" | ||||
|             ) | ||||
|  | ||||
|         return results | ||||
|  | ||||
|     try: | ||||
|         if isinstance(dep, str): | ||||
|             dep = packages[dep].to_dependency() | ||||
|  | ||||
|         _deps_of_dep(dep) | ||||
|     except KeyError as err: | ||||
|         dep_name = err.args[0] | ||||
|  | ||||
|         if dep_name in constants.UNSAFE_PACKAGES: | ||||
|         for option in packages[dep_name]: | ||||
|             if venv.is_valid_for_marker(option.to_dependency().marker): | ||||
|                 dep = option.to_dependency() | ||||
|                 break | ||||
|         else: | ||||
|             logger.warning( | ||||
|                 f"Installing package '{dep_name}' using Poetry is not supported and will be skipped" | ||||
|                 f"Skipping {dep_name}: no locked version found compatible with target python version {'.'.join([str(item) for item in venv.get_version_info()])}" | ||||
|             ) | ||||
|             logger.debug(f"Skipping {dep_name}: designated unsafe by Poetry") | ||||
|             return [] | ||||
|  | ||||
|         if dep_name in allow_missing: | ||||
|             logger.debug(f"Skipping {dep_name}: package is allowed to be unlocked") | ||||
|         return _transients(dep) | ||||
|     except KeyError as err: | ||||
|         missing = err.args[0] | ||||
|  | ||||
|         if missing in constants.UNSAFE_PACKAGES: | ||||
|             logger.warning( | ||||
|                 f"Installing package '{missing}' using Poetry is not supported and will be skipped" | ||||
|             ) | ||||
|             logger.debug(f"Skipping {missing}: designated unsafe by Poetry") | ||||
|             return [] | ||||
|  | ||||
|         if missing in allow_missing: | ||||
|             logger.debug(f"Skipping {missing}: package is allowed to be unlocked") | ||||
|             return [] | ||||
|  | ||||
|         if any( | ||||
|             delimiter in dep_name for delimiter in constants.PEP508_VERSION_DELIMITERS | ||||
|             delimiter in missing for delimiter in constants.PEP508_VERSION_DELIMITERS | ||||
|         ): | ||||
|             raise exceptions.LockedDepVersionConflictError( | ||||
|                 f"Locked dependency '{dep_name}' cannot include version specifier" | ||||
|                 f"Locked dependency '{missing}' cannot include version specifier" | ||||
|             ) from None | ||||
|  | ||||
|         raise exceptions.LockedDepNotFoundError( | ||||
|             f"No version of locked dependency '{dep_name}' found in the project lockfile" | ||||
|             f"No version of locked dependency '{missing}' found in the project lockfile" | ||||
|         ) from None | ||||
|  | ||||
|     return transients | ||||
|  | ||||
|  | ||||
| def find_project_deps( | ||||
|     packages: PackageMap, | ||||
| @@ -171,29 +205,27 @@ def find_project_deps( | ||||
|             f"Project package requires one or more unsafe dependencies ({', '.join(constants.UNSAFE_PACKAGES)}) which cannot be installed with Poetry" | ||||
|         ) | ||||
|  | ||||
|     base_deps: List[PoetryPackage] = [ | ||||
|         packages[item.name] | ||||
|         for item in poetry.package.requires | ||||
|         if not item.is_optional() | ||||
|     required_dep_names = [ | ||||
|         item.name for item in poetry.package.requires if not item.is_optional() | ||||
|     ] | ||||
|  | ||||
|     extra_deps: List[PoetryPackage] = [] | ||||
|     extra_dep_names: List[str] = [] | ||||
|     for extra in extras: | ||||
|         logger.info(f"Processing project extra '{extra}'") | ||||
|         try: | ||||
|             extra_deps += [packages[item.name] for item in poetry.package.extras[extra]] | ||||
|             extra_dep_names += [item.name for item in poetry.package.extras[extra]] | ||||
|         except KeyError: | ||||
|             raise exceptions.ExtraNotFoundError( | ||||
|                 f"Environment specifies project extra '{extra}' which was not found in the lockfile" | ||||
|             ) from None | ||||
|  | ||||
|     dependencies: List[PoetryPackage] = [] | ||||
|     for dep in base_deps + extra_deps: | ||||
|     for dep_name in required_dep_names + extra_dep_names: | ||||
|         dependencies += identify_transients( | ||||
|             dep.name.lower(), packages, venv, allow_missing=[poetry.package.name] | ||||
|             dep_name.lower(), packages, venv, allow_missing=[poetry.package.name] | ||||
|         ) | ||||
|  | ||||
|     return dependencies | ||||
|     return dedupe_packages(dependencies) | ||||
|  | ||||
|  | ||||
| def find_additional_deps( | ||||
| @@ -212,13 +244,40 @@ def find_additional_deps( | ||||
|     :param dep_names: Sequence of additional dependency names to recursively find the transient | ||||
|                       dependencies for | ||||
|     """ | ||||
|     deps: List[PoetryPackage] = [] | ||||
|     dependencies: List[PoetryPackage] = [] | ||||
|     for dep_name in dep_names: | ||||
|         deps += identify_transients( | ||||
|         dependencies += identify_transients( | ||||
|             dep_name.lower(), packages, venv, allow_missing=[poetry.package.name] | ||||
|         ) | ||||
|  | ||||
|     return deps | ||||
|     return dedupe_packages(dependencies) | ||||
|  | ||||
|  | ||||
| def find_group_deps( | ||||
|     group: str, | ||||
|     packages: PackageMap, | ||||
|     venv: "_poetry.VirtualEnv", | ||||
|     poetry: "_poetry.Poetry", | ||||
| ) -> List[PoetryPackage]: | ||||
|     """Find the dependencies belonging to a dependency group | ||||
|  | ||||
|     Recursively identify the Poetry dev dependencies | ||||
|  | ||||
|     :param group: Name of the dependency group from the project's ``pyproject.toml`` | ||||
|     :param packages: Mapping of all locked package names to their corresponding package object | ||||
|     :param venv: Poetry virtual environment to use for package compatibility checks | ||||
|     :param poetry: Poetry object for the current project | ||||
|     """ | ||||
|     return find_additional_deps( | ||||
|         packages, | ||||
|         venv, | ||||
|         poetry, | ||||
|         poetry.pyproject.data["tool"]["poetry"] | ||||
|         .get("group", {}) | ||||
|         .get(group, {}) | ||||
|         .get("dependencies", {}) | ||||
|         .keys(), | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def find_dev_deps( | ||||
| @@ -232,9 +291,26 @@ def find_dev_deps( | ||||
|     :param venv: Poetry virtual environment to use for package compatibility checks | ||||
|     :param poetry: Poetry object for the current project | ||||
|     """ | ||||
|     return find_additional_deps( | ||||
|     dev_group_deps = find_group_deps("dev", packages, venv, poetry) | ||||
|  | ||||
|     # Legacy pyproject.toml poetry format: | ||||
|     legacy_dev_group_deps = find_additional_deps( | ||||
|         packages, | ||||
|         venv, | ||||
|         poetry, | ||||
|         poetry.pyproject.data["tool"]["poetry"].get("dev-dependencies", {}).keys(), | ||||
|     ) | ||||
|  | ||||
|     # Poetry 1.2 unions these two toml sections. | ||||
|     return dedupe_packages(dev_group_deps + legacy_dev_group_deps) | ||||
|  | ||||
|  | ||||
| def dedupe_packages(packages: Sequence[PoetryPackage]) -> List[PoetryPackage]: | ||||
|     """Deduplicates a sequence of PoetryPackages while preserving ordering | ||||
|  | ||||
|     Adapted from StackOverflow: https://stackoverflow.com/a/480227 | ||||
|     """ | ||||
|     seen: Set[PoetryPackage] = set() | ||||
|     # Make this faster, avoid method lookup below | ||||
|     seen_add = seen.add | ||||
|     return [p for p in packages if not (p in seen or seen_add(p))] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user