diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 137d0dd..6b56278 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - python-version: ["3.8", "3.9"] + python-version: ["3.8", "3.9", "3.10", "3.11"] runs-on: ${{ matrix.os }} diff --git a/.pylint.ini b/.pylint.ini index 5f9db90..3f4ed55 100644 --- a/.pylint.ini +++ b/.pylint.ini @@ -51,91 +51,43 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable= - print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - missing-docstring, + fixme, + global-statement, invalid-name, + missing-docstring, + redefined-outer-name, too-few-public-methods, - fixme, + too-many-locals, too-many-arguments, + unnecessary-pass, + broad-except, + duplicate-code, too-many-branches, - keyword-arg-before-vararg, - redefined-builtin, + too-many-return-statements, too-many-public-methods, - bad-continuation, - no-member, - not-an-iterable, + too-many-ancestors, + too-many-instance-attributes, + too-many-statements, + attribute-defined-outside-init, unsupported-assignment-operation, + unsupported-delete-operation, + too-many-nested-blocks, + protected-access, + not-an-iterable, + no-member, + assigning-non-slot, + line-too-long, unsubscriptable-object, - too-many-instance-attributes, + singleton-comparison, + subprocess-run-check, too-many-lines, - line-too-long, - too-many-locals, - too-many-statements, + unnecessary-dunder-call, + redefined-builtin, + consider-using-f-string, + consider-iterating-dictionary, + use-maxsplit-arg, + use-implicit-booleaness-not-comparison, + keyword-arg-before-vararg, # 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 @@ -177,36 +129,21 @@ max-nested-blocks=5 [BASIC] -# Naming hint for argument names -argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct argument names argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for attribute names -attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct attribute names attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ -# Naming hint for class names -class-name-hint=[A-Z_][a-zA-Z0-9]+$ - # Regular expression matching correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$ -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - # Regular expression matching correct constant names const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ @@ -214,9 +151,6 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # 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_]*))$ @@ -226,21 +160,12 @@ good-names=i,j,k,ex,Run,_ # Include a hint for the correct naming format with invalid-name include-naming-hint=no -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ - # Regular expression matching correct inline iteration names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ -# Naming hint for method names -method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct method names method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ @@ -256,9 +181,6 @@ no-docstring-rgx=^_ # 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_]*))$ @@ -284,12 +206,6 @@ max-line-length=88 # 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 diff --git a/docs/requirements.txt b/docs/requirements.txt index dd04540..93c687f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ altgraph==0.17.2 ; python_version >= "3.8" and python_version < "4.0" -astroid==2.4.2 ; python_version >= "3.8" and python_version < "4.0" +astroid==2.13.5 ; python_version >= "3.8" and python_version < "4.0" astunparse==1.6.3 ; python_version >= "3.8" and python_version < "3.9" black==22.8.0 ; python_version >= "3.8" and python_version < "4.0" cached-property==1.5.2 ; python_version >= "3.8" and python_version < "4.0" @@ -10,8 +10,9 @@ click==8.1.3 ; python_version >= "3.8" and python_version < "4.0" colorama==0.4.5 ; python_version >= "3.8" and python_version < "4.0" coverage==6.4.4 ; python_version >= "3.8" and python_version < "4.0" coverage[toml]==6.4.4 ; python_version >= "3.8" and python_version < "4.0" -coveragespace==6.0 ; python_version >= "3.8" and python_version < "4.0" +coveragespace==6.1 ; python_version >= "3.8" and python_version < "4.0" datafiles==2.1.2 ; python_version >= "3.8" and python_version < "4.0" +dill==0.3.8 ; python_version >= "3.8" and python_version < "4.0" docopt==0.6.2 ; python_version >= "3.8" and python_version < "4.0" exceptiongroup==1.1.1 ; python_version >= "3.8" and python_version < "3.11" freezegun==1.2.2 ; python_version >= "3.8" and python_version < "4.0" @@ -42,20 +43,20 @@ parse==1.19.0 ; python_version >= "3.8" and python_version < "4.0" pathspec==0.10.1 ; python_version >= "3.8" and python_version < "4.0" pefile==2022.5.30 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32" platformdirs==2.5.2 ; python_version >= "3.8" and python_version < "4.0" -pluggy==1.0.0 ; python_version >= "3.8" and python_version < "4.0" +pluggy==1.5.0 ; python_version >= "3.8" and python_version < "4.0" pydocstyle==6.1.1 ; python_version >= "3.8" and python_version < "4.0" pygments==2.15.0 ; python_version >= "3.8" and python_version < "4.0" pyinstaller-hooks-contrib==2022.10 ; python_version >= "3.8" and python_version < "4.0" pyinstaller==4.5.1 ; python_version >= "3.8" and python_version < "4.0" -pylint==2.6.2 ; python_version >= "3.8" and python_version < "4.0" +pylint==2.15.10 ; python_version >= "3.8" and python_version < "4.0" pymdown-extensions==10.0 ; python_version >= "3.8" and python_version < "4.0" pync==2.0.3 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "darwin" pyparsing==3.0.9 ; python_version >= "3.8" and python_version < "4.0" -pytest-cov==4.1.0 ; python_version >= "3.8" and python_version < "4.0" -pytest-describe==2.0.1 ; python_version >= "3.8" and python_version < "4.0" +pytest-cov==5.0.0 ; python_version >= "3.8" and python_version < "4.0" +pytest-describe==2.2.0 ; python_version >= "3.8" and python_version < "4.0" pytest-expecter==3.0 ; python_version >= "3.8" and python_version < "4.0" pytest-random==0.02 ; python_version >= "3.8" and python_version < "4.0" -pytest==7.3.1 ; python_version >= "3.8" and python_version < "4.0" +pytest==8.1.2 ; python_version >= "3.8" and python_version < "4.0" python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0" python-termstyle==0.1.10 ; python_version >= "3.8" and python_version < "4.0" pytkdocs==0.16.1 ; python_version >= "3.8" and python_version < "4.0" @@ -70,7 +71,6 @@ setuptools==66.1.1 ; python_version >= "3.8" and python_version < "4.0" six==1.16.0 ; python_version >= "3.8" and python_version < "4.0" sniffer==0.4.1 ; python_version >= "3.8" and python_version < "4.0" snowballstemmer==2.2.0 ; python_version >= "3.8" and python_version < "4.0" -toml==0.10.2 ; python_version >= "3.8" and python_version < "4.0" tomli==2.0.1 ; python_version >= "3.8" and python_full_version < "3.11.0a7" tomlkit==0.10.2 ; python_version >= "3.8" and python_version < "4.0" types-freezegun==1.1.10 ; python_version >= "3.8" and python_version < "4.0" diff --git a/gitman/git.py b/gitman/git.py index 6318ad9..383c8a0 100644 --- a/gitman/git.py +++ b/gitman/git.py @@ -62,11 +62,15 @@ def clone( git("-C", normpath, "remote", "add", "-f", "origin", sparse_paths_repo) with open( - "%s/%s/.git/info/sparse-checkout" % (os.getcwd(), normpath), "w" + "%s/%s/.git/info/sparse-checkout" % (os.getcwd(), normpath), + "w", + encoding="utf-8", ) as fd: fd.write("\n".join(sparse_paths)) with open( - "%s/%s/.git/objects/info/alternates" % (os.getcwd(), normpath), "w" + "%s/%s/.git/objects/info/alternates" % (os.getcwd(), normpath), + "w", + encoding="utf-8", ) as fd: fd.write("%s/objects" % sparse_paths_repo) diff --git a/gitman/models/config.py b/gitman/models/config.py index 6e99389..e64ff04 100644 --- a/gitman/models/config.py +++ b/gitman/models/config.py @@ -329,7 +329,7 @@ def get_dependencies( def log(self, message: str = "", *args): """Append a message to the log file.""" os.makedirs(self.location_path, exist_ok=True) - with open(self.log_path, "a") as outfile: + with open(self.log_path, "a", encoding="utf-8") as outfile: outfile.write(message.format(*args) + "\n") def _get_sources(self, *, use_locked: Optional[bool] = None) -> List[Source]: diff --git a/gitman/shell.py b/gitman/shell.py index d1ddfb0..336e47e 100644 --- a/gitman/shell.py +++ b/gitman/shell.py @@ -46,14 +46,16 @@ def call(name, *args, _show=True, _stream=True, _shell=False, _ignore=False): else: env.pop(lp_key, None) # last resort: remove the env var - command = subprocess.Popen( # pylint: disable=subprocess-run-check - name if _shell else [name, *args], - encoding="utf-8", - universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - shell=_shell, - env=env, + command = ( + subprocess.Popen( # pylint: disable=subprocess-run-check,consider-using-with + name if _shell else [name, *args], + encoding="utf-8", + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=_shell, + env=env, + ) ) # Poll process.stdout to show stdout live diff --git a/gitman/tests/test_cli.py b/gitman/tests/test_cli.py index f3c37f1..1446017 100644 --- a/gitman/tests/test_cli.py +++ b/gitman/tests/test_cli.py @@ -1,4 +1,4 @@ -# pylint: disable=no-self-use,unused-variable,expression-not-assigned +# pylint: disable=unused-variable,expression-not-assigned from unittest.mock import Mock, patch diff --git a/gitman/tests/test_git.py b/gitman/tests/test_git.py index 0f591b6..1f0af9d 100644 --- a/gitman/tests/test_git.py +++ b/gitman/tests/test_git.py @@ -1,5 +1,3 @@ -# pylint: disable=no-self-use - import os from unittest.mock import Mock, patch diff --git a/gitman/tests/test_models_config.py b/gitman/tests/test_models_config.py index af4de82..ea87b6a 100644 --- a/gitman/tests/test_models_config.py +++ b/gitman/tests/test_models_config.py @@ -1,4 +1,4 @@ -# pylint: disable=no-self-use,redefined-outer-name,unused-variable,expression-not-assigned,misplaced-comparison-constant,len-as-condition +# pylint: disable=redefined-outer-name,unused-variable,expression-not-assigned,len-as-condition import os diff --git a/gitman/tests/test_models_source.py b/gitman/tests/test_models_source.py index 467c560..4f0c458 100644 --- a/gitman/tests/test_models_source.py +++ b/gitman/tests/test_models_source.py @@ -1,4 +1,4 @@ -# pylint: disable=no-self-use,redefined-outer-name,misplaced-comparison-constant +# pylint: disable=redefined-outer-name from copy import copy from unittest.mock import Mock, patch diff --git a/gitman/tests/test_plugin.py b/gitman/tests/test_plugin.py index 2a7a538..fb836d7 100644 --- a/gitman/tests/test_plugin.py +++ b/gitman/tests/test_plugin.py @@ -1,5 +1,3 @@ -# pylint: disable=no-self-use - from unittest.mock import call, patch from gitman import plugin diff --git a/gitman/tests/test_shell.py b/gitman/tests/test_shell.py index 365a7ae..9d7459d 100644 --- a/gitman/tests/test_shell.py +++ b/gitman/tests/test_shell.py @@ -1,4 +1,4 @@ -# pylint: disable=no-self-use,misplaced-comparison-constant,expression-not-assigned +# pylint: disable=expression-not-assigned import os from unittest.mock import Mock, patch diff --git a/poetry.lock b/poetry.lock index a4473d7..e686a96 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,19 +13,22 @@ files = [ [[package]] name = "astroid" -version = "2.4.2" +version = "2.13.5" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.5" +python-versions = ">=3.7.2" files = [ - {file = "astroid-2.4.2-py3-none-any.whl", hash = "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"}, - {file = "astroid-2.4.2.tar.gz", hash = "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703"}, + {file = "astroid-2.13.5-py3-none-any.whl", hash = "sha256:6891f444625b6edb2ac798829b689e95297e100ddf89dbed5a8c610e34901501"}, + {file = "astroid-2.13.5.tar.gz", hash = "sha256:df164d5ac811b9f44105a72b8f9d5edfb7b5b2d7e979b04ea377a77b3229114a"}, ] [package.dependencies] -lazy-object-proxy = "==1.4.*" -six = ">=1.12,<2.0" -wrapt = ">=1.11,<2.0" +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] [[package]] name = "astunparse" @@ -261,6 +264,21 @@ parse = ">=1.12,<2.0" "ruamel.yaml" = ">=0.17.21,<0.18.0" tomlkit = ">=0.10.1,<0.11.0" +[[package]] +name = "dill" +version = "0.3.8" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + [[package]] name = "docopt" version = "0.6.2" @@ -855,21 +873,32 @@ files = [ [[package]] name = "pylint" -version = "2.6.2" +version = "2.15.10" description = "python code static checker" optional = false -python-versions = ">=3.5.*" +python-versions = ">=3.7.2" files = [ - {file = "pylint-2.6.2-py3-none-any.whl", hash = "sha256:e71c2e9614a4f06e36498f310027942b0f4f2fde20aebb01655b31edc63b9eaf"}, - {file = "pylint-2.6.2.tar.gz", hash = "sha256:718b74786ea7ed07aa0c58bf572154d4679f960d26e9641cc1de204a30b87fc9"}, + {file = "pylint-2.15.10-py3-none-any.whl", hash = "sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e"}, + {file = "pylint-2.15.10.tar.gz", hash = "sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5"}, ] [package.dependencies] -astroid = ">=2.4.0,<2.5" -colorama = {version = "*", markers = "sys_platform == \"win32\""} +astroid = ">=2.12.13,<=2.14.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.7" -toml = ">=0.7.1" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" @@ -1260,17 +1289,6 @@ files = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1505,4 +1523,4 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>= [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "7bdcc911a273562f0e521bc14cd797a9b62e1bed2423eb9ee9a359bfbfc18bb7" +content-hash = "57db716615480e0afd7c322f9b543cbd03ce837ae24d449c0a514b1518fb3e8a" diff --git a/pyproject.toml b/pyproject.toml index 462e2c1..d330d55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ isort = "^5.10" # Linters mypy = "^1.3" pydocstyle = "*" -pylint = "~2.6" +pylint = "~2.15" types-freezegun = "*" types-setuptools = "*" diff --git a/tests/test_api.py b/tests/test_api.py index 127b765..9261a57 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -264,6 +264,7 @@ def it_should_not_overwrite_files(config_with_link): with pytest.raises(RuntimeError): gitman.install(depth=1) + @pytest.mark.skipif(os.name == "nt", reason="Test does not work on Windows") def it_should_not_overwrite_non_empty_directories(config_with_link): os.system("mkdir my_link") os.system("touch mylink/my_link") @@ -304,6 +305,7 @@ def it_should_create_links(config_with_links): expect(os.listdir()).contains("gmd_3") expect(os.listdir()).contains("gmd_4") + @pytest.mark.skipif(os.name == "nt", reason="Test does not work on Windows") def it_should_not_overwrite_files(config_with_links): os.system("touch gmd_3") @@ -1213,7 +1215,7 @@ def it_updates_the_log(config): gitman.install() gitman.list() - with open(config.log_path) as stream: + with open(config.log_path, encoding="utf-8") as stream: contents = stream.read().replace(TMP, "tmp").replace("\\", "/") expect(contents) == strip( """ @@ -1233,7 +1235,7 @@ def it_updates_the_log(config): def it_handles_missing_dependencies(config): gitman.list() - with open(config.log_path) as stream: + with open(config.log_path, encoding="utf-8") as stream: contents = stream.read().replace(TMP, "tmp").replace("\\", "/") expect(contents) == strip( """ diff --git a/tests/test_cli.py b/tests/test_cli.py index 4a590c1..8b0568c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -13,7 +13,8 @@ def config(tmpdir): tmpdir.chdir() path = str(tmpdir.join("gdm.yml")) - open(path, "w").close() + with open(path, "w", encoding="utf-8"): + pass return path @@ -21,7 +22,7 @@ def config(tmpdir): def location(tmpdir): tmpdir.chdir() path = str(tmpdir.join("gdm.yml")) - with open(path, "w") as outfile: + with open(path, "w", encoding="utf-8") as outfile: outfile.write("location: foo") return str(tmpdir.join("foo"))