Repository: tefra/xsdata
Pull request #515 (2021-06-04 22:40:02)

Use importlib for version detection
I had to add setuptools to the runtime dependencies for conda-forge recently, I am not sure what changed but yeah let's get rid of it from the runtime requirements.

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515&metric=new_duplicated_lines_density&view=list)


codecov[bot]: # [Codecov](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) Report
> Merging [#515](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) (f8ac0b7) into [master](https://codecov.io/gh/tefra/xsdata/commit/448ce451dbb834ea3a7229f73780d2505dc77f16?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) (448ce45) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/tefra/xsdata/pull/515/graphs/tree.svg?width=650&height=150&src=pr&token=YzDDLtywvl&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou)](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou)

```diff
@@            Coverage Diff            @@
##            master      #515   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           86        87    +1     
  Lines         7507      7511    +4     
  Branches      1313      1313           
=========================================
+ Hits          7507      7511    +4     
```


| [Impacted Files](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) | Coverage Δ | |
|---|---|---|
| [xsdata/cli.py](https://codecov.io/gh/tefra/xsdata/pull/515/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL2NsaS5weQ==) | `100.00% <100.00%> (ø)` | |
| [xsdata/models/config.py](https://codecov.io/gh/tefra/xsdata/pull/515/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL21vZGVscy9jb25maWcucHk=) | `100.00% <100.00%> (ø)` | |
| [xsdata/utils/compat.py](https://codecov.io/gh/tefra/xsdata/pull/515/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL3V0aWxzL2NvbXBhdC5weQ==) | `100.00% <100.00%> (ø)` | |
| [xsdata/utils/constants.py](https://codecov.io/gh/tefra/xsdata/pull/515/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL3V0aWxzL2NvbnN0YW50cy5weQ==) | `100.00% <100.00%> (ø)` | |
| [xsdata/utils/hooks.py](https://codecov.io/gh/tefra/xsdata/pull/515/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL3V0aWxzL2hvb2tzLnB5) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou). Last update [448ce45...f8ac0b7](https://codecov.io/gh/tefra/xsdata/pull/515?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou).

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=515&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=515&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=515&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/.readthedocs.yml b/.readthedocs.yml
index ced650a1..002f54d2 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -2,7 +2,7 @@ build:
   image: latest
 
 python:
-  version: 3.7
+  version: 3.8
   pip_install: true
   extra_requirements:
     - docs,cli
diff --git a/docs/_static/config.sample.xml b/docs/_static/config.sample.xml
index 8d6e2931..556d3d7d 100644
--- a/docs/_static/config.sample.xml
+++ b/docs/_static/config.sample.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Config xmlns="http://pypi.org/project/xsdata" version="21.4">
+<Config xmlns="http://pypi.org/project/xsdata" version="21.6">
   <Output maxLineLength="79">
     <Package>generated</Package>
     <Format>dataclasses</Format>
diff --git a/docs/conf.py b/docs/conf.py
index 7ece22b1..5b12bd2a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -10,9 +10,9 @@
 #
 import os
 import sys
+from importlib import metadata
 
 import sphinx_material
-from pkg_resources import get_distribution
 
 sys.path.insert(0, os.path.abspath(".."))
 
@@ -23,7 +23,7 @@ copyright = "2020, Christodoulos Tsoulloftas"
 author = "Christodoulos Tsoulloftas"
 
 # The full version, including alpha/beta/rc tags
-version = release = get_distribution("xsdata").version
+version = release = metadata.version("xsdata")
 
 # -- General configuration ---------------------------------------------------
 
diff --git a/setup.cfg b/setup.cfg
index 9e1daca1..46bf0148 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = xsdata
-version = 21.6
+version = attr: xsdata.__version__
 description = Python XML Binding
 long_description = file: README.rst
 long_description_content_type = text/x-rst
diff --git a/tox.ini b/tox.ini
index 81f9a63f..9cf429e5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,7 +12,7 @@ commands =
     tests/integration/benchmarks
 
 [testenv:docs]
-basepython = python3.7
+basepython = python3.8
 extras = docs,cli
 changedir = docs
 commands =
diff --git a/xsdata/__init__.py b/xsdata/__init__.py
index e69de29b..c669e4d4 100644
--- a/xsdata/__init__.py
+++ b/xsdata/__init__.py
@@ -0,0 +1,1 @@
+__version__ = "21.6"
diff --git a/xsdata/cli.py b/xsdata/cli.py
index 9d6ced76..19023dd1 100644
--- a/xsdata/cli.py
+++ b/xsdata/cli.py
@@ -7,8 +7,8 @@ from typing import Iterator
 import click
 import click_log
 from click_default_group import DefaultGroup
-from pkg_resources import get_distribution
 
+from xsdata import __version__
 from xsdata.codegen.transformer import SchemaTransformer
 from xsdata.codegen.writer import CodeWriter
 from xsdata.logger import logger
@@ -27,7 +27,7 @@ click_log.basic_config(logger)
 
 
 @click.group(cls=DefaultGroup, default="generate", default_if_no_args=False)
-@click.version_option(get_distribution("xsdata").version)
+@click.version_option(__version__)
 @click_log.simple_verbosity_option(logger)
 def cli():
     """xsdata command line interface."""
diff --git a/xsdata/models/config.py b/xsdata/models/config.py
index 1e3ee167..35da41bc 100644
--- a/xsdata/models/config.py
+++ b/xsdata/models/config.py
@@ -8,8 +8,7 @@ from typing import Dict
 from typing import List
 from typing import TextIO
 
-from pkg_resources import get_distribution
-
+from xsdata import __version__
 from xsdata.formats.dataclass.context import XmlContext
 from xsdata.formats.dataclass.parsers import XmlParser
 from xsdata.formats.dataclass.parsers.config import ParserConfig
@@ -256,7 +255,7 @@ class GeneratorConfig:
         name = "Config"
         namespace = "http://pypi.org/project/xsdata"
 
-    version: str = attribute(init=False, default=get_distribution("xsdata").version)
+    version: str = attribute(init=False, default=__version__)
     output: GeneratorOutput = element(default_factory=GeneratorOutput)
     conventions: GeneratorConventions = element(default_factory=GeneratorConventions)
     aliases: GeneratorAliases = element(default_factory=GeneratorAliases)


Test patch:
diff --git a/tests/models/test_config.py b/tests/models/test_config.py
index e9c9a4c8..90c1b33d 100644
--- a/tests/models/test_config.py
+++ b/tests/models/test_config.py
@@ -3,8 +3,7 @@ import warnings
 from pathlib import Path
 from unittest import TestCase
 
-from pkg_resources import get_distribution
-
+from xsdata import __version__
 from xsdata.exceptions import ParserError
 from xsdata.models.config import GeneratorConfig
 from xsdata.models.config import GeneratorOutput
@@ -25,14 +24,13 @@ class GeneratorConfigTests(TestCase):
 
     def test_create(self):
         file_path = Path(tempfile.mktemp())
-        version = get_distribution("xsdata").version
         obj = GeneratorConfig.create()
         with file_path.open("w") as fp:
             obj.write(fp, obj)
 
         expected = (
             '<?xml version="1.0" encoding="UTF-8"?>\n'
-            f'<Config xmlns="http://pypi.org/project/xsdata" version="{version}">\n'
+            f'<Config xmlns="http://pypi.org/project/xsdata" version="{__version__}">\n'
             '  <Output maxLineLength="79">\n'
             "    <Package>generated</Package>\n"
             "    <Format>dataclasses</Format>\n"
@@ -72,7 +70,6 @@ class GeneratorConfigTests(TestCase):
             "  <Aliases/>\n"
             "</Config>\n"
         )
-        version = get_distribution("xsdata").version
         file_path = Path(tempfile.mktemp())
         file_path.write_text(existing, encoding="utf-8")
         config = GeneratorConfig.read(file_path)
@@ -81,7 +78,7 @@ class GeneratorConfigTests(TestCase):
 
         expected = (
             '<?xml version="1.0" encoding="UTF-8"?>\n'
-            f'<Config xmlns="http://pypi.org/project/xsdata" version="{version}">\n'
+            f'<Config xmlns="http://pypi.org/project/xsdata" version="{__version__}">\n'
             '  <Output maxLineLength="79">\n'
             "    <Package>foo.bar</Package>\n"
             "    <Format>dataclasses</Format>\n"