codecov[bot]: # [Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=h1) Report
> Merging [#1213](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=desc) into [master](https://codecov.io/gh/raiden-network/raiden-contracts/commit/a1993ade92c46d117801628a58409be4e480a3a8?src=pr&el=desc) will **decrease** coverage by `0.11%`.
> The diff coverage is `0%`.

[![Impacted file tree graph](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213/graphs/tree.svg?width=650&token=q8aKDUjiN7&height=150&src=pr)](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1213      +/-   ##
==========================================
- Coverage   81.14%   81.03%   -0.12%     
==========================================
  Files          21       21              
  Lines        1453     1455       +2     
  Branches      191      192       +1     
==========================================
  Hits         1179     1179              
- Misses        231      232       +1     
- Partials       43       44       +1
```


| [Impacted Files](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [raiden\_contracts/utils/join-contracts.py](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213/diff?src=pr&el=tree#diff-cmFpZGVuX2NvbnRyYWN0cy91dGlscy9qb2luLWNvbnRyYWN0cy5weQ==) | `90.9% <0%> (-3.44%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=footer). Last update [a1993ad...31f0d5c](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

codecov[bot]: # [Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=h1) Report
> Merging [#1213](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=desc) into [master](https://codecov.io/gh/raiden-network/raiden-contracts/commit/a1993ade92c46d117801628a58409be4e480a3a8?src=pr&el=desc) will **decrease** coverage by `0.11%`.
> The diff coverage is `0%`.

[![Impacted file tree graph](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213/graphs/tree.svg?width=650&token=q8aKDUjiN7&height=150&src=pr)](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1213      +/-   ##
==========================================
- Coverage   81.14%   81.03%   -0.12%     
==========================================
  Files          21       21              
  Lines        1453     1455       +2     
  Branches      191      192       +1     
==========================================
  Hits         1179     1179              
- Misses        231      232       +1     
- Partials       43       44       +1
```


| [Impacted Files](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [raiden\_contracts/utils/join-contracts.py](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213/diff?src=pr&el=tree#diff-cmFpZGVuX2NvbnRyYWN0cy91dGlscy9qb2luLWNvbnRyYWN0cy5weQ==) | `90.9% <0%> (-3.44%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=footer). Last update [a1993ad...31f0d5c](https://codecov.io/gh/raiden-network/raiden-contracts/pull/1213?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

pirapira: CodeCov complains.  It's a good time to add tests.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eadd9e3..cf336c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ Documents changes that result in:
 
 ## Unreleased
 
+- [#1213](https://github.com/raiden-network/raiden-contracts/pull/1213) etherscan_verify.py now fails when a source imports a nonexistent file.
+
 ## [0.31.0](https://github.com/raiden-network/raiden-contracts/releases/tag/v0.31.0) - 2019-08-20
 
 - [#1163](https://github.com/raiden-network/raiden-contracts/pull/1163) MonitoringService.monitor() no longer works for service providers that are not registered in ServiceRegistry
diff --git a/raiden_contracts/utils/join_contracts.py b/raiden_contracts/utils/join_contracts.py
index b5cdd61..1a42e03 100755
--- a/raiden_contracts/utils/join_contracts.py
+++ b/raiden_contracts/utils/join_contracts.py
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 import json
-import os
 import re
 import sys
 from typing import Dict, List, Set, TextIO
@@ -61,9 +60,8 @@ class ContractJoiner:
             for prefix, path in self.import_map.items():
                 if next_file.startswith(prefix):
                     next_file = next_file.replace(prefix, path)
-            if next_file and os.path.exists(next_file):
-                with open(next_file) as next_contract:
-                    out.extend(self.join(next_contract))
+            with open(next_file) as next_contract:
+                out.extend(self.join(next_contract))
 
 
 @click.command()

join-contracts.py should complain about  missing imports
Currently, `join-contracts.py` succeeds silently when some of the imported files are not found. This issue keeps track of making `join-contracts.py` fail for missing imports.


#### Current behavior
`TokenNetwork.sol` imports many contracts, but it gets smaller after `join-contracts.py` processing.

```
$ utils/join-contracts.py contracts/TokenNetwork.sol flat.sol && wc -l contracts/TokenNetwork.sol flat.sol
Reading contracts/TokenNetwork.sol
  1684 contracts/TokenNetwork.sol
  1679 flat.sol
  3363 total
```
diff --git a/raiden_contracts/tests/test_contract_joiner.py b/raiden_contracts/tests/test_contract_joiner.py
new file mode 100644
index 0000000..cce4c3d
--- /dev/null
+++ b/raiden_contracts/tests/test_contract_joiner.py
@@ -0,0 +1,25 @@
+from tempfile import NamedTemporaryFile
+
+import pytest
+
+from raiden_contracts.utils.join_contracts import ContractJoiner
+
+
+def test_contract_joiner_with_non_existent_import() -> None:
+    """ Using ContractJoiner on a source importing a nonexistent file """
+    joiner = ContractJoiner()
+    source_with_missing_import = """
+        import "NonExistent.sol";
+    """
+    with NamedTemporaryFile() as source_file:
+        source_file.write(bytearray(source_with_missing_import, "ascii"))
+        source_file.flush()
+        with pytest.raises(FileNotFoundError):
+            joiner.join(open(source_file.name))
+
+
+def test_contract_joiner_with_empty_file() -> None:
+    """ Using ContractJoiner on an empty source """
+    joiner = ContractJoiner()
+    with NamedTemporaryFile() as source_file:
+        assert [] == joiner.join(open(source_file.name))

pip install -U -r requirements-dev.txt && pip install -e .
parse_log_pytest
requirements.txt
pytest
3.7
requirements.txt requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
asn1crypto==1.5.1
astroid==2.15.8
attrdict==2.0.1
attrs==24.2.0
autopep8==2.0.0
black==23.3.0
bump2version==1.0.1
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
charset-normalizer==3.4.1
click==8.1.8
coincurve==18.0.0
coverage==7.2.7
cryptography==2.9.2
cytoolz==0.12.3
dill==0.3.7
eth-abi==1.2.2
eth-account==0.3.0
eth-bloom==1.0.4
eth-hash==0.3.3
eth-keyfile==0.5.1
eth-keys==0.2.4
eth-rlp==0.2.1
eth-tester==0.1.0b33
eth-typing==1.3.0
eth-utils==1.8.1
exceptiongroup==1.2.2
flake8==5.0.4
flake8-bugbear==23.3.12
flake8-commas==2.1.0
flake8-tuple==0.4.1
hexbytes==0.3.1
hypothesis==3.44.14
idna==3.10
importlib-metadata==4.2.0
iniconfig==2.0.0
isort==5.11.5
lazy-object-proxy==1.9.0
lru-dict==1.2.0
mccabe==0.7.0
mypy==0.720
mypy-extensions==0.4.4
packaging==24.0
parsimonious==0.8.1
pathspec==0.11.2
pipdeptree==2.9.6
platformdirs==4.0.0
pluggy==1.2.0
py-ecc==1.4.7
py-evm==0.2.0a33
py-solc==3.2.0
pycodestyle==2.9.1
pycparser==2.21
pycryptodome==3.22.0
pyethash==0.1.27
pyfakefs==5.8.0
pyflakes==2.5.0
pylint==2.17.7
pylint-quotes==0.2.3
pysha3==1.0.2
pytest==7.4.4
pytest-cov==4.1.0
-e git+https://github.com/raiden-network/raiden-contracts.git@b9b8fd49f66a9ced22d1c3aba746471fe86ea6c3#egg=raiden_contracts
requests==2.31.0
requests-mock==1.12.1
rlp==1.2.0
semantic-version==2.10.0
semver==3.0.4
six==1.17.0
tomli==2.0.1
tomlkit==0.12.5
toolz==0.12.1
trie==1.4.0
typed-ast==1.4.3
typing_extensions==4.7.1
urllib3==2.0.7
web3==4.10.0
websockets==6.0
wrapt==1.16.0
zipp==3.15.0

name: raiden-contracts
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - asn1crypto==1.5.1
      - astroid==2.15.8
      - attrdict==2.0.1
      - attrs==24.2.0
      - autopep8==2.0.0
      - black==23.3.0
      - bump2version==1.0.1
      - cffi==1.15.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - coincurve==18.0.0
      - coverage==7.2.7
      - cryptography==2.9.2
      - cytoolz==0.12.3
      - dill==0.3.7
      - eth-abi==1.2.2
      - eth-account==0.3.0
      - eth-bloom==1.0.4
      - eth-hash==0.3.3
      - eth-keyfile==0.5.1
      - eth-keys==0.2.4
      - eth-rlp==0.2.1
      - eth-tester==0.1.0b33
      - eth-typing==1.3.0
      - eth-utils==1.8.1
      - exceptiongroup==1.2.2
      - flake8==5.0.4
      - flake8-bugbear==23.3.12
      - flake8-commas==2.1.0
      - flake8-tuple==0.4.1
      - hexbytes==0.3.1
      - hypothesis==3.44.14
      - idna==3.10
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - isort==5.11.5
      - lazy-object-proxy==1.9.0
      - lru-dict==1.2.0
      - mccabe==0.7.0
      - mypy==0.720
      - mypy-extensions==0.4.4
      - packaging==24.0
      - parsimonious==0.8.1
      - pathspec==0.11.2
      - pipdeptree==2.9.6
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - py-ecc==1.4.7
      - py-evm==0.2.0a33
      - py-solc==3.2.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pycryptodome==3.22.0
      - pyethash==0.1.27
      - pyfakefs==5.8.0
      - pyflakes==2.5.0
      - pylint==2.17.7
      - pylint-quotes==0.2.3
      - pysha3==1.0.2
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - requests==2.31.0
      - requests-mock==1.12.1
      - rlp==1.2.0
      - semantic-version==2.10.0
      - semver==3.0.4
      - six==1.17.0
      - tomli==2.0.1
      - tomlkit==0.12.5
      - toolz==0.12.1
      - trie==1.4.0
      - typed-ast==1.4.3
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - web3==4.10.0
      - websockets==6.0
      - wrapt==1.16.0
      - zipp==3.15.0
prefix: /opt/conda/envs/raiden-contracts

raiden_contracts/tests/test_contract_joiner.py::test_contract_joiner_with_non_existent_import
raiden_contracts/tests/test_contract_joiner.py::test_contract_joiner_with_empty_file
raiden_contracts/utils/join_contracts.py CHANGELOG.md
raiden_contracts/utils/join_contracts.py CHANGELOG.md