Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,44 @@
project(pysearch)
set(
SRC
bindings.cpp
)
include_directories(${CMAKE_BINARY_DIR})
omim_add_library(${PROJECT_NAME} MODULE ${SRC})
omim_link_libraries(
${PROJECT_NAME}
search_quality
search_tests_support
search
storage
editor
indexer
geometry
ge0
platform
mwm_diff
coding
base
bsdiff
ICU::i18n
cppjansson
opening_hours
protobuf
pugixml
succinct
${Boost_LIBRARIES}
ZLIB::ZLIB
)
link_qt5_core(${PROJECT_NAME})
link_qt5_network(${PROJECT_NAME})
if (PLATFORM_MAC)
omim_link_libraries(${PROJECT_NAME} "-Wl,-undefined,dynamic_lookup")
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")

View file

@ -0,0 +1,46 @@
This document describes how to use this module.
1. How to build?
To build the module you need Python3.7 (or higher) and Boost Python. Also, you
need Qt5.5 (or higher), but you need it in any case if you're
planning to build the project. On MacOS, Python3.7 should be
installed by default, to get Boost via Brew just type in the shell:
brew update
brew install boost-python3
On Debian, type in the shell:
sudo apt-get install libboost-*
Note that on MacOS Boost is built by default with libc++, on Debian
Boost is built by default with libstdc++. Therefore, you can use
only macx-clang and linux-clang specs correspondingly. It's wrong
to use linux-clang-libc++ because it's generally a bad idea to have
two implementations of the C++ standard library in the same
application.
Then, invoke cmake from the shell, for example:
cmake <path-to-omim-directory>\
-DPYBINDINGS=ON\
-DPYBINDINGS_VERSION=3.7\
-DPYTHON_INCLUDE_DIRS=<path-to-dir-with-Python.h>\
-DCMAKE_PREFIX_PATH=<path-to-qt5.5>
make -k -j8 pysearch
To set the python paths correctly, refer to https://cmake.org/cmake/help/v3.0/module/FindPythonLibs.html
and
python-config --includes
2. How to use?
As pysearch is a custom Python module, all that you need
is to customize PYTHONPATH environment variable before running your
scripts. For example:
PYTHONPATH=path-to-the-directory-with-pysearch.so \
./search/pysearch/run_search_engine.py

View file

@ -0,0 +1,251 @@
#include "search/engine.hpp"
#include "search/search_quality/helpers.hpp"
#include "search/search_tests_support/test_search_engine.hpp"
#include "search/search_tests_support/test_search_request.hpp"
#include "search/tracer.hpp"
#include "indexer/classificator_loader.hpp"
#include "indexer/data_source.hpp"
#include "storage/storage_defines.hpp"
#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"
#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "pyhelpers/module_version.hpp"
#include <boost/python.hpp>
#include <iomanip>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "defines.hpp"
using namespace std;
namespace
{
struct Mercator
{
Mercator() = default;
Mercator(double x, double y) : m_x(x), m_y(y) {}
explicit Mercator(m2::PointD const & m) : m_x(m.x), m_y(m.y) {}
string ToString() const
{
ostringstream os;
os << "x: " << m_x << ", y: " << m_y;
return os.str();
}
double m_x = 0.0;
double m_y = 0.0;
};
struct Viewport
{
Viewport() = default;
Viewport(Mercator const & min, Mercator const & max) : m_min(min), m_max(max) {}
string ToString() const
{
ostringstream os;
os << "[" << m_min.ToString() << ", " << m_max.ToString() << "]";
return os.str();
}
Mercator m_min;
Mercator m_max;
};
struct Params
{
string ToString() const
{
ostringstream os;
os << m_query << ", " << m_locale << ", " << m_position.ToString() << ", " << m_viewport.ToString();
return os.str();
}
string m_query;
string m_locale;
Mercator m_position;
Viewport m_viewport;
};
struct Result
{
Result() = default;
explicit Result(search::Result const & r)
{
m_name = r.GetString();
m_address = r.GetAddress();
m_hasCenter = r.HasPoint();
if (m_hasCenter)
m_center = Mercator(r.GetFeatureCenter());
}
string ToString() const
{
ostringstream os;
os << m_name << " [ " << m_address;
if (m_hasCenter)
os << ", " << m_center.ToString();
os << " ]";
return os.str();
}
string m_name;
string m_address;
bool m_hasCenter = false;
Mercator m_center;
};
struct TraceResult
{
string ToString() const
{
ostringstream os;
os << "parse: [" << strings::JoinStrings(m_parse, ", ") << "], ";
os << "is_category: " << boolalpha << m_isCategory;
return os.str();
}
vector<string> m_parse;
bool m_isCategory = false;
};
struct SearchEngineProxy
{
SearchEngineProxy()
{
search::search_quality::InitDataSource(m_dataSource, "" /* mwmListPath */);
search::search_quality::InitStorageData(m_affiliations, m_countryNameSynonyms);
m_engine =
search::search_quality::InitSearchEngine(m_dataSource, m_affiliations, "en" /* locale */, 1 /* numThreads */);
}
search::SearchParams MakeSearchParams(Params const & params) const
{
search::SearchParams sp;
sp.m_query = params.m_query;
sp.m_inputLocale = params.m_locale;
sp.m_mode = search::Mode::Everywhere;
sp.m_position = m2::PointD(params.m_position.m_x, params.m_position.m_y);
sp.m_needAddress = true;
auto const & bottomLeft = params.m_viewport.m_min;
auto const & topRight = params.m_viewport.m_max;
sp.m_viewport = m2::RectD(bottomLeft.m_x, bottomLeft.m_y, topRight.m_x, topRight.m_y);
return sp;
}
boost::python::list Query(Params const & params) const
{
m_engine->SetLocale(params.m_locale);
search::tests_support::TestSearchRequest request(*m_engine, MakeSearchParams(params));
request.Run();
boost::python::list results;
for (auto const & result : request.Results())
results.append(Result(result));
return results;
}
boost::python::list Trace(Params const & params) const
{
m_engine->SetLocale(params.m_locale);
auto sp = MakeSearchParams(params);
auto tracer = make_shared<search::Tracer>();
sp.m_tracer = tracer;
search::tests_support::TestSearchRequest request(*m_engine, sp);
request.Run();
boost::python::list trs;
for (auto const & parse : tracer->GetUniqueParses())
{
TraceResult tr;
for (size_t i = 0; i < parse.m_ranges.size(); ++i)
{
auto const & range = parse.m_ranges[i];
if (!range.Empty())
tr.m_parse.push_back(ToString(static_cast<search::Tracer::Parse::TokenType>(i)));
}
tr.m_isCategory = parse.m_category;
trs.append(tr);
}
return trs;
}
storage::Affiliations m_affiliations;
storage::CountryNameSynonyms m_countryNameSynonyms;
FrozenDataSource m_dataSource;
unique_ptr<search::tests_support::TestSearchEngine> m_engine;
};
void Init(string const & dataPath, string const & mwmPath)
{
classificator::Load();
search::search_quality::SetPlatformDirs(dataPath, mwmPath);
}
} // namespace
BOOST_PYTHON_MODULE(pysearch)
{
using namespace boost::python;
scope().attr("__version__") = PYBINDINGS_VERSION;
def("init", &Init);
class_<Mercator>("Mercator")
.def(init<double, double>())
.def_readwrite("x", &Mercator::m_x)
.def_readwrite("y", &Mercator::m_y)
.def("to_string", &Mercator::ToString);
class_<Viewport>("Viewport")
.def(init<Mercator const &, Mercator const &>())
.def_readwrite("min", &Viewport::m_min)
.def_readwrite("max", &Viewport::m_max)
.def("to_string", &Viewport::ToString);
class_<Params>("Params")
.def_readwrite("query", &Params::m_query)
.def_readwrite("locale", &Params::m_locale)
.def_readwrite("position", &Params::m_position)
.def_readwrite("viewport", &Params::m_viewport)
.def("to_string", &Params::ToString);
class_<Result>("Result")
.def_readwrite("name", &Result::m_name)
.def_readwrite("address", &Result::m_address)
.def_readwrite("has_center", &Result::m_hasCenter)
.def_readwrite("center", &Result::m_center)
.def("__repr__", &Result::ToString);
class_<TraceResult>("TraceResult")
.def_readwrite("parse", &TraceResult::m_parse)
.def_readwrite("is_category", &TraceResult::m_isCategory)
.def("__repr__", &TraceResult::ToString);
class_<SearchEngineProxy, boost::noncopyable>("SearchEngine")
.def("query", &SearchEngineProxy::Query)
.def("trace", &SearchEngineProxy::Trace);
}

View file

@ -0,0 +1,29 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import os
import pysearch as search
DIR = os.path.dirname(__file__)
RESOURCE_PATH = os.path.realpath(os.path.join(DIR, '..', '..', 'data'))
MWM_PATH = os.path.realpath(os.path.join(DIR, '..', '..', 'data'))
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-r', metavar='RESOURCE_PATH', default=RESOURCE_PATH, help='Path to resources directory.')
parser.add_argument('-m', metavar='MWM_PATH', default=MWM_PATH, help='Path to mwm files.')
args = parser.parse_args()
search.init(args.r, args.m)
engine = search.SearchEngine()
params = search.Params()
params.query = 'кафе юность'
params.locale = 'ru'
params.position = search.Mercator(37.618705, 67.455669)
params.viewport = search.Viewport(search.Mercator(37.1336, 67.1349),
search.Mercator(38.0314, 67.7348))
print(engine.query(params))
print(engine.trace(params))

View file

@ -0,0 +1,79 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import print_function
from http.server import BaseHTTPRequestHandler,HTTPServer
import argparse
import json
import os
import pysearch
import urllib.parse
DIR = os.path.dirname(__file__)
RESOURCE_PATH = os.path.realpath(os.path.join(DIR, '..', '..', 'data'))
MWM_PATH = os.path.realpath(os.path.join(DIR, '..', '..', 'data'))
PORT=8080
class HTTPHandler(BaseHTTPRequestHandler):
def do_GET(self):
result = urllib.parse.urlparse(self.path)
query = urllib.parse.parse_qs(result.query)
def sparam(name):
return query[name][-1]
def fparam(name):
return float(sparam(name))
params = pysearch.Params()
try:
params.query = sparam('query')
params.locale = sparam('locale')
params.position = pysearch.Mercator(fparam('posx'), fparam('posy'))
params.viewport = pysearch.Viewport(
pysearch.Mercator(fparam('minx'), fparam('miny')),
pysearch.Mercator(fparam('maxx'), fparam('maxy')))
except KeyError:
self.send_response(400)
return
results = HTTPHandler.engine.query(params)
responses = [{'name': result.name,
'address': result.address,
'has_center': result.has_center,
'center': {'x': result.center.x,
'y': result.center.y
}
}
for result in results]
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(responses).encode())
def main(args):
pysearch.init(args.r, args.m)
engine = pysearch.SearchEngine()
HTTPHandler.engine = pysearch.SearchEngine()
print('Starting HTTP server on port', PORT)
server = HTTPServer(('', args.p), HTTPHandler)
server.serve_forever()
if __name__ == '__main__':
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-r', metavar='RESOURCE_PATH', default=RESOURCE_PATH,
help='Path to resources directory.')
parser.add_argument('-m', metavar='MWM_PATH', default=MWM_PATH,
help='Path to mwm files.')
parser.add_argument('-p', metavar='PORT', default=PORT,
help='Port for the server to listen')
args = parser.parse_args()
main(args)

View file

@ -0,0 +1,13 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
module_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(module_dir, '..', '..'))
from pyhelpers.setup import setup_omim_pybinding
NAME = "pysearch"
setup_omim_pybinding(name=NAME)