populus
populus copied to clipboard
Parse and normalize import remappings.
What was wrong?
In populus/compilation/__init__.py the solidity import remappings from the settings file are passed into the compiler backend.
Import remappings, as they are passed to the compiler should be a list of strings in one of the following two formats.
import-path-from-source-file/=actual-import-path/contracts/SourceFile.sol:import-path-from-source-file/=actual-import-path/
When the provided paths are absolute, this generally works, but when they are relative paths which is much more common, this fails when the paths are outside of the populus project directory.
How can it be fixed.
Since import remappings are in a well known format, we can parse these values and then normalize them to absolute paths. Write the following new functions in populus.utils.compile to do this.
from eth_utils import (
to_tuple,
)
def normalize_import_remapping(import_remapping):
source_path, _, remainder = import_remapping.rpartition(':')
import_path, _, remapped_path = remainder.partition('=')
abs_remapped_path = os.path.abspath(remapped_path)
if source_path:
return "{0}:{1}={2}".format(source_path, import_path, abs_remapped_path)
else:
return "{0}={1}".format(import_path, abs_remapped_path)
def process_import_remappings(import_remappings):
for item in import_remappings:
yield normalize_import_remapping(item)
The code above should be tested in tests/compile-utils/test_normalize_import_remappings to be sure it works as expected (since I wrote it here in this issue and haven't tested it myself).
Before the import remappings are passed into the compiler backend,
Cute Animal Picture

It needed a few changes from the code you have above, but I believe I have this working. There's just one thing I can't seem to figure out.
I get an error at tests/compilation/test_solc_standard_json_backend.py::test_compiling_with_local_import_remappings ERROR
The error I get states that the solidity file is outside of the allowed directories. I've confirmed that the directory in the error does exist, and does have the solidity file. I can access that file without sudo.
I can't figure out why it should be any different using the absolute path vs relative. It's the same folder, why is it suddenly unable to access it?
The full error:
E solc.exceptions.SolcError: contracts/ImportRemappingTestA.sol:3:1: ParserError: Source "/private/tmp/pytest-of-root/pytest-0/test_compiling_with_local_impo0/project-dir/contracts/RemapImported.sol" not found: File outside of allowed directories.
E import {RemapImported} from "import-path-for-A/RemapImported.sol";
E ^----------------------------------------------------------------^
E
E > command: `solc --standard-json`
E > return code: `0`
E > stderr:
E {"contracts":{},"errors":[{"component":"general","formattedMessage":"contracts/ImportRemappingTestA.sol:3:1: ParserError: Source \"/private/tmp/pytest-of-root/pytest-0/test_compiling_with_local_impo0/project-dir/contracts/RemapImported.sol\" not found: File outside of allowed directories.\nimport {RemapImported} from \"import-path-for-A/RemapImported.sol\";\n^----------------------------------------------------------------^\n","message":"Source \"/private/tmp/pytest-of-root/pytest-0/test_compiling_with_local_impo0/project-dir/contracts/RemapImported.sol\" not found: File outside of allowed directories.","severity":"error","type":"ParserError"}],"sources":{}}
E
E > stdout:
Again, I can access the file referred to with no issue.
cat /private/tmp/pytest-of-root/pytest-0/test_compiling_with_local_impo0/project-dir/contracts/RemapImported.sol
pragma solidity ^0.4.0;
contract RemapImported {
function RemapImported() public {
}
}
contract RemapImportedNotUsed {
function RemapImportedNotUsed() public {
}
}