Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd7a9be6

Browse files
dee-me-tree-or-loveFlorian Boudinet
and
Florian Boudinet
authored
Feat: integrating prefix server mounting option from#647 (#655)
Follow-up of@skapin 's work in#647---------* [FEATURE] add params to start server on prefix example.com/my/server/prefix/<routes>* chore: black formatting* chore: add a config test* chore: add a container test for prefixed server* fix: use the prefix when waiting for container* fix: type fix* chore: formatting* fix: semantics* fix: fixtures* chore: docs and cleanup- added docs to README- small cleanups in code and readme* chore: doc cleanup + TOC---------Co-authored-by: Florian Boudinet <florian.boudinet@eshard.com>
1 parent917a56c commitd7a9be6

File tree

5 files changed

+155
-12
lines changed

5 files changed

+155
-12
lines changed

‎README.md‎

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Table of Contents
8383
-[Custom Health Check Endpoint](#custom-health-check-endpoint)
8484
-[Configure a custom health endpoint by CLI arguments](#configure-a-custom-health-endpoint-by-cli-arguments)
8585
-[Configure a custom health endpoint by script](#configure-a-custom-health-endpoint-by-script)
86+
-[Exposing`pypi-server` on a URL with a custom prefix](#exposing-pypi-server-on-a-url-with-a-custom-prefix)
8687
-[Sources](#sources)
8788
-[Known Limitations](#known-limitations)
8889
-[Similar Projects](#similar-projects)
@@ -154,9 +155,9 @@ Table of Contents
154155

155156
```text
156157
usage: pypi-server [-h] [-v] [--log-file FILE] [--log-stream STREAM]
157-
[--log-frmt FORMAT] [--hash-algo HASH_ALGO]
158-
[--backend {auto,simple-dir,cached-dir}] [--version]
159-
{run,update} ...
158+
[--log-frmt FORMAT] [--hash-algo HASH_ALGO]
159+
[--backend {auto,simple-dir,cached-dir}] [--version]
160+
{run,update} ...
160161
161162
start PyPI compatible package server serving packages from PACKAGES_DIRECTORY. If PACKAGES_DIRECTORY is not given on the command line, it uses the default ~/packages. pypiserver scans this directory recursively for packages. It skips packages and directories starting with a dot. Multiple package directories may be specified.
162163
@@ -169,7 +170,7 @@ Table of Contents
169170
printed to stdout for introspection or pipelining. See
170171
the `-x` option for updating packages directly.
171172
172-
optional arguments:
173+
options:
173174
-h, --help show this help message and exit
174175
-v, --verbose Enable verbose logging; repeat for more verbosity.
175176
--log-file FILE Write logging info into this FILE, as well as to
@@ -208,12 +209,13 @@ usage: pypi-server run [-h] [-v] [--log-file FILE] [--log-stream STREAM]
208209
[-o] [--welcome HTML_FILE] [--cache-control AGE]
209210
[--log-req-frmt FORMAT] [--log-res-frmt FORMAT]
210211
[--log-err-frmt FORMAT]
211-
[package_directory [package_directory ...]]
212+
[--server-base-url SERVER_BASE_URL]
213+
[package_directory ...]
212214
213215
positional arguments:
214216
package_directory The directory from which to serve packages.
215217
216-
optional arguments:
218+
options:
217219
-h, --help show this help message and exit
218220
-v, --verbose Enable verbose logging; repeat for more verbosity.
219221
--log-file FILE Write logging info into this FILE, as well as to
@@ -295,7 +297,9 @@ optional arguments:
295297
--log-err-frmt FORMAT
296298
A format-string selecting Http-Error properties to
297299
log; set to '%s' to see them all.
298-
300+
--server-base-url SERVER_BASE_URL
301+
Serve all routes under SERVER_BASE_URL prefix
302+
(default: {DEFAULTS.SERVER_BASE_URL})
299303
```
300304

301305
###More details about pypi-server update
@@ -308,12 +312,12 @@ usage: pypi-server update [-h] [-v] [--log-file FILE] [--log-stream STREAM]
308312
[--backend {auto,simple-dir,cached-dir}] [--version]
309313
[-x] [-d DOWNLOAD_DIRECTORY] [-u]
310314
[--blacklist-file IGNORELIST_FILE]
311-
[package_directory[package_directory...]]
315+
[package_directory ...]
312316
313317
positional arguments:
314318
package_directory The directory from which to serve packages.
315319
316-
optional arguments:
320+
options:
317321
-h, --help show this help message and exit
318322
-v, --verbose Enable verbose logging; repeat for more verbosity.
319323
--log-file FILE Write logging info into this FILE, as well as to
@@ -1147,6 +1151,31 @@ bottle.run(app=app, host="0.0.0.0", port=8080, server="auto")
11471151
11481152
Try**curl<http://localhost:8080/action/health>**
11491153
1154+
### Exposing `pypi-server` on a URL with a custom prefix
1155+
1156+
The`--server-base-url` config option enables hosting your`pypi-server` deployment behind aURL prefix.
1157+
1158+
It can come handy when you are exposing`pypi-server` through a proxyor ingress.
1159+
1160+
1. Start the serverwith a customURL prefix:
1161+
1162+
```bash
1163+
pypi-server run--server-base-url/prefix/
1164+
```
1165+
1166+
1. And itis accessible at the followingURL:
1167+
1168+
```bash
1169+
$ curl http://localhost:8080/prefix/
1170+
<htmllang="en">
1171+
<head>
1172+
<metacharset="utf-8">
1173+
<title>Welcome to pypiserver!</title>
1174+
</head>
1175+
<body>
1176+
# ...
1177+
```
1178+
11501179
## Sources
11511180
11521181
To create a copy of the repository, use

‎docker/test_docker.py‎

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,13 @@ def image() -> str:
9191
returntag
9292

9393

94-
defwait_for_container(port:int)->None:
94+
defwait_for_container(port:int,url_path:t.Optional[str]=None)->None:
9595
"""Wait for the container to be available."""
9696
for_inrange(60):
9797
try:
98-
httpx.get(f"http://localhost:{port}").raise_for_status()
98+
httpx.get(
99+
f"http://localhost:{port}"+ (url_pathifurl_pathelse"")
100+
).raise_for_status()
99101
except (httpx.RequestError,httpx.HTTPStatusError):
100102
time.sleep(1)
101103
else:
@@ -701,3 +703,79 @@ def test_download(self, container: ContainerInfo) -> None:
701703
"pypiserver_mypkg_heavy"inpath.name
702704
forpathinPath(tmpdir).iterdir()
703705
)
706+
707+
708+
classTestServerPrefix:
709+
prefix_url="/prefix/"
710+
711+
@pytest.fixture(scope="class")
712+
defcontainer(
713+
self,request:pytest.FixtureRequest,image:str
714+
)->t.Iterator[ContainerInfo]:
715+
"""Run the pypiserver container.
716+
717+
Returns the container ID.
718+
"""
719+
port=get_socket()
720+
args= (
721+
"docker",
722+
"run",
723+
"--rm",
724+
"--publish",
725+
f"{port}:8080",
726+
"--detach",
727+
image,
728+
"run",
729+
"--passwords",
730+
".",
731+
"--authenticate",
732+
".",
733+
"--server-base-url",
734+
self.prefix_url,
735+
)
736+
res=run(*args,capture=True)
737+
wait_for_container(port,url_path=self.prefix_url)
738+
container_id=res.out.strip()
739+
yieldContainerInfo(container_id,port,args)
740+
run("docker","container","rm","-f",container_id)
741+
742+
@pytest.fixture(scope="class")
743+
defupload_mypkg(
744+
self,
745+
container:ContainerInfo,
746+
mypkg_paths:t.Dict[str,Path],
747+
)->None:
748+
"""Upload mypkg to the container."""
749+
run(
750+
sys.executable,
751+
"-m",
752+
"twine",
753+
"upload",
754+
"--repository-url",
755+
f"http://localhost:{container.port}{self.prefix_url}",
756+
"--username",
757+
"a",
758+
"--password",
759+
"a",
760+
f"{mypkg_paths['dist_dir']}/*",
761+
)
762+
763+
@pytest.mark.usefixtures("upload_mypkg")
764+
deftest_download(self,container:ContainerInfo)->None:
765+
"""Download mypkg from the container."""
766+
withtempfile.TemporaryDirectory()astmpdir:
767+
run(
768+
sys.executable,
769+
"-m",
770+
"pip",
771+
"download",
772+
"--index-url",
773+
f"http://localhost:{container.port}{self.prefix_url}simple",
774+
"--dest",
775+
tmpdir,
776+
"pypiserver_mypkg",
777+
)
778+
assertany(
779+
"pypiserver_mypkg"inpath.name
780+
forpathinPath(tmpdir).iterdir()
781+
)

‎pypiserver/__main__.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,15 @@ def main(argv: t.Sequence[str] = None) -> None:
200200
"Running bottle with selected server '%s'",config.server_method
201201
)
202202

203+
# We strip&check because bottle mount() will raise error if path has no segment.
204+
ifconfig.server_base_url.strip("/"):
205+
main_app=bottle.Bottle()
206+
main_app.mount(config.server_base_url,app)
207+
else:
208+
main_app=app
209+
203210
bottle.run(
204-
app=app,
211+
app=main_app,
205212
host=config.host,
206213
port=config.port,
207214
server=config.server_method,

‎pypiserver/config.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class DEFAULTS:
124124
PORT=8080
125125
SERVER_METHOD="auto"
126126
BACKEND="auto"
127+
SERVER_BASE_URL= (
128+
"/"# if server need to served under example.com/<SERVER_BASE_URL>
129+
)
127130

128131

129132
defauth_arg(arg:str)->t.List[str]:
@@ -518,6 +521,14 @@ def get_parser() -> argparse.ArgumentParser:
518521
),
519522
)
520523

524+
run_parser.add_argument(
525+
"--server-base-url",
526+
default=DEFAULTS.SERVER_BASE_URL,
527+
help=(
528+
"Serve all routes under SERVER_BASE_URL prefix (default: {DEFAULTS.SERVER_BASE_URL})"
529+
),
530+
)
531+
521532
update_parser=subparsers.add_parser(
522533
"update",
523534
help=textwrap.dedent(
@@ -723,6 +734,7 @@ def __init__(
723734
log_req_frmt:str,
724735
log_res_frmt:str,
725736
log_err_frmt:str,
737+
server_base_url:str,
726738
auther:t.Optional[t.Callable[[str,str],bool]]=None,
727739
**kwargs:t.Any,
728740
)->None:
@@ -742,6 +754,7 @@ def __init__(
742754
self.log_req_frmt=log_req_frmt
743755
self.log_res_frmt=log_res_frmt
744756
self.log_err_frmt=log_err_frmt
757+
self.server_base_url=server_base_url
745758
# Derived properties
746759
self._derived_properties=self._derived_properties+ ("auther",)
747760
self.auther=self.get_auther(auther)
@@ -767,6 +780,7 @@ def kwargs_from_namespace(
767780
"log_req_frmt":namespace.log_req_frmt,
768781
"log_res_frmt":namespace.log_res_frmt,
769782
"log_err_frmt":namespace.log_err_frmt,
783+
"server_base_url":namespace.server_base_url,
770784
}
771785

772786
defget_auther(

‎tests/test_config.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,21 @@ def generate_subcommand_test_cases(
575575
),
576576
},
577577
),
578+
# server prefix
579+
ConfigTestCase(
580+
case="Run: default server base prefix is /",
581+
args=["run"],
582+
legacy_args=[],
583+
exp_config_type=RunConfig,
584+
exp_config_values={"server_base_url":"/"},
585+
),
586+
ConfigTestCase(
587+
case="Run: specified server base prefix is set",
588+
args=["run","--server-base-url","/prefix"],
589+
legacy_args=["--server-base-url","/prefix"],
590+
exp_config_type=RunConfig,
591+
exp_config_values={"server_base_url":"/prefix"},
592+
),
578593
# ******************************************************************
579594
# Update subcommand args
580595
# ******************************************************************

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp