PyLint "Unable to import" error - how to set PYTHONPATH?
Asked Answered
I

35

333

I'm running PyLint from inside Wing IDE on Windows. I have a sub-directory (package) in my project and inside the package I import a module from the top level, ie.

__init__.py
myapp.py
one.py
subdir\
    __init__.py
    two.py

Inside two.py I have import one and this works fine at runtime, because the top-level directory (from which myapp.py is run) is in the Python path. However, when I run PyLint on two.py it gives me an error:

F0401: Unable to import 'one'

How do I fix this?

Infelicitous answered 14/12, 2009 at 7:22 Comment(0)
E
261

There are two options I'm aware of.

One, change the PYTHONPATH environment variable to include the directory above your module.

Alternatively, edit ~/.pylintrc to include the directory above your module, like this:

[MASTER]
init-hook='import sys; sys.path.append("/path/to/root")'

(Or in other version of pylint, the init-hook requires you to change [General] to [MASTER])

Both of these options ought to work.

Edric answered 17/6, 2010 at 19:46 Comment(15)
This pylint hook is currently the best way in VScode as PYTHONPATH isn't yet supported for it's built in linter usage.Aluminiferous
I have the same issue using MacVim with syntastic. How can I configure prosector to fix the import error ?Numerical
Related blog post with a few more details.Costin
~/.pylintrc worked for me on OSX, the other didn't workDuquette
Not sure why this is not the accepted answer - also, worth mentioning for those stumbling on this, that you need to export PYTHONPATH so that pylint will see it (at least, in bash/zsh)Zaccaria
This is the only way I've made pylint work with VScode with the most recent updates of VSC and the python plugin. Adding PYTHONPATH or python.autoComplete.extraPaths to settings.json did not work.Thelma
For VS Code, I was able to set the PYTHONPATH to a relative path inside an .env file, and it picked that up.Griffy
Can't we solve this using the python -m pylint flag?Hawsehole
How to set PYTHONPATH is discussed here: #3702146Outdated
Where should we keep the .pylintrc file with respect to the project root? The solution is not working for me.Roberts
Unfortunately, it ends with the new wrong-import-positionCirculate
I had a look at the current Pylint code and the section name MASTER is actually ignored (but must still be present). Another thing is that you can pass this on the command line --init-hook (not tested).Sapless
Indeed it was using the --init-hook command line option(with pylint.args inside .vscode/settings.json) that worked for me. Putting the same option in .pylintrc never worked(although the file is indeed used by pylint run from within VSCode). Thanks @Timmmm.Armalla
Reflecting on my previous comment, I found out that putting the lines in .pylintrc takes effect only after you restart VSCode. Putting them though in .vscode/settings.json takes effect immediately.Armalla
to make it portable: 'import sys; import os; sys.path.append(os.path.dirname(__file__))'Marduk
T
136

The solution to alter path in init-hook is good, but I dislike the fact that I had to add absolute path there, as result I can not share this pylintrc file among the developers of the project. This solution using relative path to pylintrc file works better for me:

[MASTER]
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"

Note that pylint.config.PYLINTRC also exists and has the same value as find_pylintrc().

Tawanda answered 29/8, 2016 at 13:15 Comment(5)
Confirming that this really did supply the solution for E0611 and E0401 pylint errors. For VSCode users: It is important the the opened folder is the "python root folder", and that the .pylintrc is in that folder.Geter
also, make sure none of your module directory names start with . (dot).Tamtama
if you want to add a specific sub-folder (i.e. app) you can use from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), 'app'))Niveous
In my setup the package in question was outside the root of the project, therefore my line looks like this: init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()),".."))"Politesse
This won't work if you are using pyproject.toml file, use this instead: from pylint.config import find_default_config_files; import os, sys; sys.path.append(os.path.dirname(next(find_default_config_files())))Tailpiece
K
76

The problem can be solved by configuring pylint path under venv: $ cat .vscode/settings.json

{
    "python.pythonPath": "venv/bin/python",
    "python.linting.pylintPath": "venv/bin/pylint"
}
Kreisler answered 24/12, 2018 at 2:22 Comment(7)
For Windows it's { "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" } Just for completeness.Gatha
VSCode now shows this message: The setting "python.pythonPath" defined in your settings.json is now deprecated. If I delete the python.pythonPath line it still seems to work though.Deerdre
Simple as that. That sounds way better than altering import paths. That works perfectly for anyone using poetry (which creates its virtual environment in .venv/ by default): "python.linting.pylintPath": "${workspaceFolder}/.venv/bin/pylint",Stettin
Adding "python.linting.pylintPath": "venv/bin/pylint" was enough to me, although I already had pythonPath setMalvin
This doesn't look related to the OP. It says nothing about a vscode-specific implementation.Dagan
Thank you @cglacet! Works great for me with poetry and vs code.Taite
Also, isn't wouldin't this only work for local linting? I assume (though I'm by no means a Python expert) this doesn't help if you have some deployment side linting going on either in a build process (thinking containers) or other "production-side" situations where you might want your deploy to run a lint check before allowing a deploy or potentially version control action before allowing merge to main?Conversazione
M
47

Create .pylintrc and add

[MASTER]
init-hook="from pylint.config import find_pylintrc;
import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
Mezoff answered 19/1, 2020 at 11:4 Comment(2)
This link name perplexes meAche
I would add that this file should be placed in the directory that you want added to PYTHONPATH. Also, this only worked for me if the double-quoted commands are on a single line instead of two, as above.Flossie
J
44

I've added a new file pylintrc in the project's root directory with

[MASTER]
init-hook='import sys; sys.path.append(".")'

and it works for me in PyCharm IDE

Jarred answered 23/3, 2021 at 16:58 Comment(2)
This is the only answer that work on my computer. I tried other answers above but doesn't work.Shiksa
works like a charm; note you can use either of pylintrc or .pylintrcTribrach
A
41

Do you have an empty __init__.py file in both directories to let python know that the dirs are modules?

The basic outline when you are not running from within the folder (ie maybe from pylint's, though I haven't used that) is:

topdir\
  __init__.py
  functions_etc.py
  subdir\
    __init__.py
    other_functions.py

This is how the python interpreter is aware of the module without reference to the current directory, so if pylint is running from its own absolute path it will be able to access functions_etc.py as topdir.functions_etc or topdir.subdir.other_functions, provided topdir is on the PYTHONPATH.

UPDATE: If the problem is not the __init__.py file, maybe just try copying or moving your module to c:\Python26\Lib\site-packages -- that is a common place to put additional packages, and will definitely be on your pythonpath. If you know how to do Windows symbolic links or the equivalent (I don't!), you could do that instead. There are many more options here: http://docs.python.org/install/index.html, including the option of appending sys.path with the user-level directory of your development code, but in practice I usually just symbolically link my local development dir to site-packages - copying it over has the same effect.

Anaplastic answered 14/12, 2009 at 7:45 Comment(4)
Yes, I do have __init__.py in both directories. I think the problem is that the top dir is NOT in PYTHONPATH when PyLint runs and I'm not sure how to fix that.Infelicitous
The symlink is a good idea, but it's only supported from Windows Vista onwards and I'm running XP. I suppose I could try hard-linking it...Infelicitous
re hardlinking: No, you better don't do it. I've played with it and, while it certainly works (in a way), it will not work as you expect.Perchloride
Symlinks are not a good idea. This only fixes the problem on your machine - when someone else checks out the project, it will be broken for them.Aerial
B
32

1) sys.path is a list.

2) The problem is sometimes the sys.path is not your virtualenv.path and you want to use pylint in your virtualenv

3) So like said, use init-hook (pay attention in ' and " the parse of pylint is strict)

[Master]
init-hook='sys.path = ["/path/myapps/bin/", "/path/to/myapps/lib/python3.3/site-packages/", ... many paths here])'

or

[Master]
init-hook='sys.path = list(); sys.path.append("/path/to/foo")'

.. and

pylint --rcfile /path/to/pylintrc /path/to/module.py
Batchelor answered 29/4, 2014 at 21:6 Comment(0)
N
9

I don't know how it works with WingIDE, but for using PyLint with Geany, I set my external command to:

PYTHONPATH=${PYTHONPATH}:$(dirname %d) pylint --output-format=parseable --reports=n "%f"

where %f is the filename, and %d is the path. Might be useful for someone :)

Novick answered 12/11, 2010 at 8:12 Comment(0)
B
5

I had to update the system PYTHONPATH variable to add my App Engine path. In my case I just had to edit my ~/.bashrc file and add the following line:

export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder

In fact, I tried setting the init-hook first but this did not resolve the issue consistently across my code base (not sure why). Once I added it to the system path (probably a good idea in general) my issues went away.

Bindweed answered 11/9, 2016 at 15:30 Comment(0)
P
4

Try

if __name__ == '__main__':
    from [whatever the name of your package is] import one
else:
    import one

Note that in Python 3, the syntax for the part in the else clause would be

from .. import one

On second thought, this probably won't fix your specific problem. I misunderstood the question and thought that two.py was being run as the main module, but that is not the case. And considering the differences in the way Python 2.6 (without importing absolute_import from __future__) and Python 3.x handle imports, you wouldn't need to do this for Python 2.6 anyway, I don't think.

Still, if you do eventually switch to Python 3 and plan on using a module as both a package module and as a standalone script inside the package, it may be a good idea to keep something like

if __name__ == '__main__':
    from [whatever the name of your package is] import one   # assuming the package is in the current working directory or a subdirectory of PYTHONPATH
else:
    from .. import one

in mind.

EDIT: And now for a possible solution to your actual problem. Either run PyLint from the directory containing your one module (via the command line, perhaps), or put the following code somewhere when running PyLint:

import os

olddir = os.getcwd()
os.chdir([path_of_directory_containing_module_one])
import one
os.chdir(olddir)

Basically, as an alternative to fiddling with PYTHONPATH, just make sure the current working directory is the directory containing one.py when you do the import.

(Looking at Brian's answer, you could probably assign the previous code to init_hook, but if you're going to do that then you could simply do the appending to sys.path that he does, which is slightly more elegant than my solution.)

Pase answered 17/6, 2010 at 20:3 Comment(0)
M
4

I found a nice answer. Edit your pylintrc and add the following in master

init-hook="import imp, os; from pylint.config import find_pylintrc; imp.load_source('import_hook', os.path.join(os.path.dirname(find_pylintrc()), 'import_hook.py'))"
Medallist answered 17/9, 2019 at 17:51 Comment(0)
U
4

If you want to walk up from the current module/file that was handed to pylint looking for the root of the module, this will do it.

[MASTER]
init-hook=sys.path += [os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i])) for i, _ in enumerate(sys.argv[-1].split(os.sep)) if os.path.isdir(os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i], '.git')))][::-1]

If you have a python module ~/code/mymodule/, with a top-level directory layout like this

~/code/mymodule/
├── .pylintrc
├── mymodule/
│   └── src.py
└── tests/
    └── test_src.py

Then this will add ~/code/mymodule/ to your python path and allow for pylint to run in your IDE, even if you're importing mymodule.src in tests/test_src.py.

You could swap out a check for a .pylintrc instead but a git directory is usually what you want when it comes to the root of a python module.

Before you ask

The answers using import sys, os; sys.path.append(...) are missing something that justifies the format of my answer. I don't normally write code that way, but in this case you're stuck dealing with the limitations of the pylintrc config parser and evaluator. It literally runs exec in the context of the init_hook callback so any attempt to import pathlib, use multi-line statements, store something into variables, etc., won't work.

A less disgusting form of my code might look like this:

import os
import sys

def look_for_git_dirs(filename):
    has_git_dir = []
    filename_parts = filename.split(os.sep)
    for i, _ in enumerate(filename_parts):
        filename_part = os.path.abspath(os.path.join(os.path.sep, *filename_parts[:i]))
        if os.path.isdir(os.path.join(filename_part, '.git')):
            has_git_dir.append(filename_part)
    return has_git_dir[::-1]

# don't use .append() in case there's < 1 or > 1 matches found
sys.path += look_for_git_dirs(sys.argv[-1])

I wish I could have used pathlib.Path(filename).parents it would have made things much easier.

Unimproved answered 12/11, 2020 at 22:20 Comment(1)
Although not really suggested, it is possible to import using __import__ function which might be handy hereSacrilege
K
3

I had the same problem and since i could not find a answer I hope this can help anyone with a similar problem.

I use flymake with epylint. Basically what i did was add a dired-mode-hook that check if the dired directory is a python package directory. If it is I add it to the PYTHONPATH. In my case I consider a directory to be a python package if it contains a file named "setup.py".

;;;;;;;;;;;;;;;;;
;; PYTHON PATH ;;
;;;;;;;;;;;;;;;;;

(defun python-expand-path ()
  "Append a directory to the PYTHONPATH."
  (interactive
   (let ((string (read-directory-name 
          "Python package directory: " 
          nil 
          'my-history)))
     (setenv "PYTHONPATH" (concat (expand-file-name string)
                  (getenv ":PYTHONPATH"))))))

(defun pythonpath-dired-mode-hook ()
  (let ((setup_py (concat default-directory "setup.py"))
    (directory (expand-file-name default-directory)))
    ;;   (if (file-exists-p setup_py)
    (if (is-python-package-directory directory)
    (let ((pythonpath (concat (getenv "PYTHONPATH") ":" 
                  (expand-file-name directory))))
      (setenv "PYTHONPATH" pythonpath)
      (message (concat "PYTHONPATH=" (getenv "PYTHONPATH")))))))

(defun is-python-package-directory (directory)
  (let ((setup_py (concat directory "setup.py")))
    (file-exists-p setup_py)))

(add-hook 'dired-mode-hook 'pythonpath-dired-mode-hook)

Hope this helps.

Kosse answered 9/11, 2013 at 23:11 Comment(0)
M
3

The key is to add your project directory to sys.path without considering about the env variable.

For someone who use VSCode, here's a one-line solution for you if there's a base directory of your project:

[MASTER]
init-hook='base_dir="my_spider"; import sys,os,re; _re=re.search(r".+\/" + base_dir, os.getcwd()); project_dir = _re.group() if _re else os.path.join(os.getcwd(), base_dir); sys.path.append(project_dir)'

Let me explain it a little bit:

  • re.search(r".+\/" + base_dir, os.getcwd()).group(): find base directory according to the editing file

  • os.path.join(os.getcwd(), base_dir): add cwd to sys.path to meet command line environment


FYI, here's my .pylintrc:

https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f

Musset answered 15/5, 2016 at 13:9 Comment(1)
This is the only solution that works for me. It isn't ideal, but certainly better than nothing.Nightclub
G
3

I had this same issue and fixed it by installing pylint in my virtualenv and then adding a .pylintrc file to my project directory with the following in the file:

[Master]
init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")'
Granddaughter answered 26/7, 2016 at 17:17 Comment(1)
I have to confirm that this gets rid of the E0611 pylint errors, but the E0401 errors remain.Geter
S
3

When you install Python, you can set up the path. If path is already defined then what you can do is within VS Code, hit Ctrl+Shift+P and type Python: Select Interpreter and select updated version of Python. Follow this link for more information, https://code.visualstudio.com/docs/python/environments

Schenck answered 18/7, 2020 at 2:41 Comment(0)
B
3

First, go to your VS Code then press "ctrl + shift + p"

Then search settings.json

Then paste the below code inside the settings.jason.I hope the problem will be solved.

{

"python.pythonPath": "venv/bin/python",
"python.linting.pylintPath": "venv/bin/pylint"

}

Biddick answered 11/10, 2020 at 13:52 Comment(1)
"python.pythonPath": ".venv\\Scripts\\python.exe", "python.linting.pylintPath": ".venv\\Scripts\\pylint.exe" in Windows.Vasodilator
S
3

I got this error when trying to submit a PR. What I end up doing is just to add #pylint: disable=E0401 on the same line where "import" happens.

This helps me to pass the auto test.

Stroganoff answered 22/7, 2021 at 17:50 Comment(0)
O
3

this all work for me!

.pylintrc

[MASTER]
; init-hook='import sys; sys.path.append("./venv/lib/python3.8/site-packages")'

; or
init-hook='import sys; sys.path.append(f"./venv/lib/python{sys.version[:3]}/site-packages");'

; or
;init-hook='from distutils.sysconfig import get_python_lib; sys.path.append(get_python_lib())'

; or
; init-hook='import site; sys.path.append(site.getsitepackages()[0])'
Orbiculate answered 14/5, 2022 at 3:44 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewZendavesta
I
2

One workaround that I only just discovered is to actually just run PyLint for the entire package, rather than a single file. Somehow, it manages to find imported module then.

Infelicitous answered 16/12, 2009 at 6:15 Comment(3)
Sounds great; how?Vasodilator
@CeesTimmerman Run pylint ... dir from parent folder. This requires __init__.py to be present in each subfolder with .py files.Oehsen
In many contexts (such as getting syntactical feedback in an editor) this is not useful.Redundant
D
2

This is an old question but has no accepted answer, so I'll suggest this: change the import statement in two.py to read:

from .. import one

In my current environment (Python 3.6, VSCode using pylint 2.3.1) this clears the flagged statement.

Duckling answered 23/8, 2019 at 18:20 Comment(0)
A
2

I found this worked nicely in my local .pylintrc file with a pipenv virtual environment:

[MASTER]
init-hook='import site; sys.path += site.getsitepackages()'

See this post for info about site packages.

Agrippina answered 19/6, 2021 at 6:2 Comment(0)
F
1

In case anybody is looking for a way to run pylint as an external tool in PyCharm and have it work with their virtual environments (why I came to this question), here's how I solved it:

  1. In PyCharm > Preferences > Tools > External Tools, Add or Edit an item for pylint.
  2. In the Tool Settings of the Edit Tool dialog, set Program to use pylint from the python interpreter directory: $PyInterpreterDirectory$/pylint
  3. Set your other parameters in the Parameters field, like: --rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
  4. Set your working directory to $FileDir$

Now using pylint as an external tool will run pylint on whatever directory you have selected using a common config file and use whatever interpreter is configured for your project (which presumably is your virtualenv interpreter).

Frederik answered 2/5, 2016 at 16:15 Comment(0)
S
1

Hello i was able to import the packages from different directory. I just did the following: Note: I am using VScode

Steps to Create a Python Package Working with Python packages is really simple. All you need to do is:

  • Create a directory and give it your package's name.
  • Put your classes in it.
  • Create a __init__.py file in the directory

For example: you have a folder called Framework where you are keeping all the custom classes there and your job is to just create a __init__.py file inside the folder named Framework.

And while importing you need to import in this fashion--->

from Framework import base

so the E0401 error disappears Framework is the folder where you just created __init__.py and base is your custom module which you are required to import into and work upon Hope it helps!!!!

Sortie answered 9/7, 2018 at 7:1 Comment(0)
C
1

Mac user: If you're using Anaconda 3 w/ vsCode and have multiple environments, pointing to the following path via settings.json for vsCode works as well:

{
  "python.pythonPath": "/Users/username/opt/anaconda3/bin/python",
  "python.linting.pylintPath": "/Users/username/opt/anaconda3/bin/python"
}
Contrariety answered 17/3, 2021 at 16:44 Comment(1)
python != pylint so you merely disabled Pylint there.Vasodilator
L
1

If you are using Windows:

  • get the path of the python.exe inside the virtual environment you just created
  • it should be like this Z:\YourProjectFolder\Scripts\python.exe
  • then go to your vscode and edit the user settings.json
  • add this line: "python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
  • save it and that should fix the issue
  • NOTE: the double backslash instead of single when putting it to the json file
{
    "python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
}
Leucippus answered 2/4, 2021 at 15:36 Comment(0)
W
0

Maybe by manually appending the dir inside the PYTHONPATH?

sys.path.append(dirname)
Woodprint answered 15/12, 2009 at 12:8 Comment(3)
Hmm, but where would you put that code? At the top of each and every file? I suppose it would work, but it's quite a hack just to get PyLint to work.Infelicitous
@Evgeny: See the answer that Brian M. Hunt recently posted.Pase
And adding this at the top of every file doesn't work for some reason - PyLint seems perfectly content to ignore any modifications to sys.path made from within modules it's scanning. I haven't bothered to research why, though...Excel
C
0

if you using vscode,make sure your package directory is out of the _pychache__ directory.

Clem answered 21/11, 2018 at 8:15 Comment(1)
Also with VS code, there seem to be potential issues with dot in folder names: github.com/PyCQA/pylint/issues/2182Flight
P
0

If you are using Cython in Linux, I resolved removing module.cpython-XXm-X-linux-gnu.so files in my project target directory.

Prudhoe answered 11/9, 2019 at 12:57 Comment(0)
N
0

just add this code in .vscode/settings.json file

,"python.linting.pylintPath": "venv/bin/pylint"

This will notify the location of pylint(which is an error checker for python)

Nightrider answered 30/6, 2020 at 18:50 Comment(1)
You should really mention that venv is your local virtual environment directory. You probably want to add ${workspaceFolder} at the start of the path.Springwood
D
0

I have been struggling with this a lot and eventually found out something that was not described here. Here are my 2 cents to this issue: I am using VS Code on Windows, using virtual env. For some reasons, the pylint executable is called epylint and not pylint. In my script or from CLI prompt, I was running pylint ./xxx and the system was launching a pylint it found somewhere else but not the appropriate one. I just added an e in my shell script and my 'Unable to import' issues eventually vanished.

Deme answered 13/1, 2022 at 11:12 Comment(0)
F
0

edit ~/.pylintrc to include the directory above your module, like this:

[MASTER]
init-hook='import sys,os;[sys.path.append("your_workspace_path"+di) for di in os.listdir("your_workspace_path")]'
Firewarden answered 16/2, 2022 at 13:6 Comment(0)
C
0

Throwing another potential answer onto the pile. I tried a lot of the solutions presented here. Either I did them incorrectly or my pylint import error was caused by something different. Regardless my solution was pretty simple.

Solution: reinstall whichever package (PyPi package not pip package) that contains all the modules you are unable to import and then reinstall pylint so that pylint and those modules are installed by the same pip.

For me, having the correct directory did not work. I got this idea from reading another thread about his issue.

Chancery answered 9/5, 2022 at 6:46 Comment(0)
O
0

There is no need to create .pylintrc if You are sure You won't mess up Your imports. You can turn off the import errors using the --disable import-error argument in the console/settings.

If You're using Pylint through the console - add --disable import-error as an argument.

If You're using a Pylint code editor plugin in an IDE - there should be a setting where You can define the arguments.

In PyCharm, You'd put that in Settings -> Other Settings -> Pylint -> Arguments.

Modern coding IDEs should point out common mistakes with imports that You probably could catch Yourself anyway. Is spending precious time (money) creating specific pylintrcs a good investment if You ignore the error?

Otila answered 29/6, 2023 at 15:5 Comment(0)
H
0

I ran into the same issue and found a different solution. Some of the solutions already presented here didn't work or were not desirable for me.

  • First, I am using pylint version 3.0.3 and find_pylintrc is not present anymore.
  • I didn't want to use absolute paths in init-root.
  • I wanted to be IDE independent, so tweaking PyCharm configuration is not possible.
  • I wanted it to be committed to repository so it had to work for others and can't contain absolute paths.

The solution in my case was to add the following snippet to the MAIN section of the pylintrc file. (You may have something different than MAIN if you are using a different version of pylint).

[MAIN]
source-roots=repository/apps,src/apps

The list of source roots are either absolute or relative to the working folder from where pylint is being called, or the project root folder in case pylint is called from within the IDE.

Hagiographer answered 31/1 at 16:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.